旋转卡壳

该算法一般用于求凸包上两点间的最大距离。

方法一:

     从任意一个顶点开始,按逆时针方向计算其他每一点到该顶点的距离。使距离为一直是递增的,直到开始递减;然后记录下这一次的最大值。

     然后移动为基础的那个点,从上次中断的点开始;再重复上述步骤,直到距离又递减为止。

     所有的最大值即是凸包的直径。

 

方法二:

    任意取一条边,计算每一个点到该条边的距离,直到距离开始递减;具体和方法一相似。

 

代码实现(凸包的周长,直径:方法二)

 

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define maxn 50100        //the max number of the points
struct point{ 
   double x, y;
   };
point pnt[maxn];         //cin's points
point res[maxn];         //the points on convex hill
int n, l;               //the number of the points
bool mult(point sp, point ep, point op){
     return (sp.x - op.x) * (ep.y - op.y) >= (ep.x - op.x) * (sp.y - op.y);
}         //cross project
 
bool operator <(const point &l, const point &r){   
       return l.y < r.y || (l.y == r.y && l.x < r.x);
}         //cmp
 
int graham(point pnt[], int n, point res[]){
    int i, len, top = 1; 
    sort(pnt, pnt + n);  
    if (n == 0)       
       return 0;    
    res[0] = pnt[0];
      if (n == 1)
         return 1;
    res[1] = pnt[1];    
    if (n == 2)  
        return 2;   
    res[2] = pnt[2];    
    for (i = 2; i < n; i++){
         while (top && mult(pnt[i], res[top], res[top - 1]))   
                 top--;       
         res[++top] = pnt[i];
        } 
    len = top; 
    res[++top] = pnt[n - 2];    
    for (i = n - 3; i >= 0; i--){       
       while (top != len && mult(pnt[i], res[top], res[top - 1]))   
             top--;      
       res[++top] = pnt[i];  
       }  
    return top;
}          //to be a convex hill

double cross(point a, point b, point o){
        return (a.x - o.x) * (b.y - o.y) - (b.x - o.x) * (a.y - o.y);
}

double dis(point &p, point &q){   
       double x1 = p.x - q.x, y1 = p.y - q.y; 
             return (x1 * x1 + y1 * y1);
}          //get the distance of two points

double maxlen(point *ch, int n){              //ch is res[]'s first address  , n is res[]'s lenth
       int q = 1;
       double ans = 0;    
       ch[n] = ch[0];                        //let the convex fill round
       for (int p = 0; p < n; p++){
            while (cross(ch[p + 1], ch[q + 1], ch[p]) > cross(ch[p + 1], ch[q], ch[p]))         //p,p+1 is the ver and q is the points
                 q = (q + 1) % n;       
                 ans = max(ans, max(dis(ch[p], ch[q]), dis(ch[p + 1], ch[q + 1])));       //get the max lenth
       }    
      return ans;
}

int main(){    
          //    freopen("t.txt", "r", stdin);  
      while(scanf("%d", &n)!=EOF){
      for (int i = 0; i < n; i++)     
      scanf("%lf%lf", &pnt[i].x, &pnt[i].y);   
      int tot = graham(pnt, n, res); //tot is the number of the points one convex hill     
      for (int i = 0; i < tot; i++)       // 0 to tot-1 on res is the points on convex
            ans += dis(res[i], res[(i + 1) % tot]);     //get the while lenth of the convex
      printf("%.0f\n", ans);  
      double tlen=maxlen(res,tot);
      printf("%.0f\n",tlen);
      }
      return 0;
}

 

    

posted on 2012-08-22 21:24  yumao  阅读(242)  评论(0)    收藏  举报

导航