Graham_Scan解决凸包问题

来源:互联网 发布:淘宝商家的宝贝删不掉 编辑:程序博客网 时间:2024/05/16 08:04

人类对于未知的事物,第一反应总是恐惧的。


大一在ACM做题的时候,遇到过一个凸包问题。然后看其他同学下了个模板,朦朦胧胧的给过了,就感觉这么难!网上都有模板了,自己看来是写不出这种模板的。


现在看了算法导论,想想当时的自己,已经哭晕在厕所。


Graham_Scan算法,主要是对于数学的叉积的理论的熟悉比较重要,向量p1p0 ( x1 , y1 ) 叉积 p2p0( x2 , y2 )  : ( x1 * y2 ) - ( y1 * x2 )。结果为正的,则表示p2p0向量在p1p0向量的左侧。


而在Graham_Scan算法里,因为要将所有的点都包起来,所以B点距离下一个点C,则B点之前的A点与C点构成的向量与B点与C点构成的向量的叉积肯定是要负的,如果是正的,则要将B点排除出凸包边上点集合。


public class Graham_Scan {public void Scan(Node[] ns){Node[] Q = new Node[ns.length];//保存凸包边上的点;int top = 0;//保存 栈顶位置int k = 0 ;for(int i = 1 ; i < ns.length ; i ++)if (ns[i].y < ns[k].y || (ns[i].y == ns[k].y && ns[i].x < ns[k].x)) k = i;Node tmp = ns[k];ns[k] = ns[0];ns[0] = tmp;for(int i = 1 ; i < ns.length ; i ++){k = i;for(int j = i + 1 ; j < ns.length ; j ++){if ( (cross(ns[j], ns[k], ns[0]) > 0 ) || ( cross(ns[j], ns[k], ns[0]) == 0 && dist(ns[j], ns[0]) < dist(ns[k], ns[0]) ) ) {k = j;}}tmp = ns[k];ns[k] = ns[i];ns[i] = tmp;}top = -1;Q[++top] = ns[0];Q[++top] = ns[1];Q[++top] = ns[2];for(int i = 3; i < ns.length ; i ++){while (cross(ns[i], Q[top], Q[top - 1]) > 0) {//top --;}Q[++top] = ns[i];}}private int cross(Node n1, Node n2, Node n0){int sign = (n1.x - n0.x)*(n2.y - n0.y) - (n2.x - n0.x)*(n2.y - n0.y);return sign;}private double dist(Node n1 , Node n2){return Math.sqrt((n1.x - n2.x)*(n1.x - n2.x) + (n1.y - n2.y)*(n1.y - n2.y));}private class Node{private int x;private int y;}}


0 0