poj2187
題意:求一個點集中的兩個點的最遠距離的平方。
分析:點集可以先用Graham-scan求凸包,再用Rotating Caliper求多邊形外接圓直徑。注意旋轉卡殼中具體是先固定一條邊,作為三角形的底邊,再依次枚舉除這兩個點之外的其他點(逆時針順序),用叉積求三角形的面積,面積最大時表明邊與點的距離最遠。
#include <cstdio> #include <cmath> #include <algorithm> #define vector point using std::sort; using std::swap; using std::max; const double PI = acos(-1.00); struct point {int x,y;point(int xx = 0,int yy = 0){x = xx;y = yy;}point operator - (point s){return point(x - s.x, y - s.y);}double len(){return sqrt(x * x + y * y + 0.0);}int len2(){return x * x + y * y;} };point p[50010]; int n,l,hull_list[50010];int cross_product(vector v1,vector v2) {return v1.x * v2.y - v1.y * v2.x; }bool cmp(point& a,point& b) {int cp = cross_product(vector(a - p[0]),vector(b - p[0]));if(cp > 0 || (cp == 0 && vector((a - p[0])).len2() < vector((b - p[0])).len2() ) )return true;elsereturn false; }//基點取p[0],逆時針掃描,返回凸包上的點數 int Graham_scan() {int top = 1;sort(p + 1,p + n,cmp);hull_list[0] = 0;hull_list[1] = 1;for(int i = 2;i < n;i++){while(top >= 1 && cross_product(vector(p[hull_list[top]] - p[hull_list[top - 1]]),vector(p[i] - p[hull_list[top]])) <= 0)//<=為一條邊上只留兩個頂點,<則為一條邊上可以留多個頂點top--;hull_list[++top] = i;}return top + 1; }//旋轉卡殼求最遠點對的距離的平方,p[]的大小要比n的最大值多2,凸包點集的順序為逆時針 int rotating_caliper(point p[],int& n) {int counter = 0,dis = 0;p[n] = p[0];p[n + 1] = p[1];int j = 2;for(int i = 0;i < n;i++){while(cross_product(p[i + 1] - p[i],p[j] - p[i]) < cross_product(p[i + 1] - p[i],p[j + 1] - p[i]))j = (j + 1) % n;dis = max(max((p[i] - p[j]).len2(),(p[i + 1] - p[j]).len2()),dis);}return dis; }int main() {while(~scanf("%d",&n)){int lowest = 0;for(int i = 0;i < n;i++){scanf("%d%d",&p[i].x,&p[i].y);if(p[lowest].y > p[i].y || (p[lowest].y == p[i].y && p[lowest].x > p[i].x))lowest = i;}swap(p[lowest],p[0]);l = Graham_scan();for(int i = 0;i < l;i++)p[i] = p[hull_list[i]];printf("%d\n",rotating_caliper(p,l));}return 0; }?
轉載于:https://www.cnblogs.com/ZShogg/archive/2013/05/08/3067110.html
總結
- 上一篇: 数据库表连接查询
- 下一篇: 掌握技术思想比解决问题本身更重要