1393: Robert Hood 旋转卡壳 凸包

http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1393

http://poj.org/problem?id=2187 Beauty Contest

1393: Robert Hood

 

Description

1393: Robert Hood 旋转卡壳 凸包_第1张图片

Input

1393: Robert Hood 旋转卡壳 凸包_第2张图片

Output

Sample Input

5
-4 1
-100 0
0 4
2 -3
2 300

Sample Output

316.86590223

HINT

 

1393: Robert Hood 旋转卡壳 凸包_第3张图片

 

Source

 

 

分析:

给你 N 个点, 求所有点中最远两点距离。即是凸包直径。

凸包+旋转卡壳 

 

AC代码:

 1 #include<stdio.h>
 2 #include<math.h>
 3 #include<string.h>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 const int maxn = 100000+10;
 8 int n,m;
 9 
10 struct Point{
11     double x,y;
12     Point(){};
13     Point(double _x, double _y)
14     {
15         x = _x;
16         y = _y;
17     }
18 
19     Point operator - (const Point & B) const
20     {
21         return Point(x-B.x, y-B.y);
22     }
23 }p[maxn], ch[maxn];
24 
25 bool cmp(Point p1, Point p2)
26 {
27     if(p1.x == p2.x) return p1.y < p2.y;
28     return p1.x < p2.x;
29 }
30 
31 int squarDist(Point A, Point B) /**距离的平方*/
32 {
33     return (A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y);
34 }
35 
36 double Cross(Point A, Point B) /**叉积*/
37 {
38     return A.x*B.y-A.y*B.x;
39 }
40 
41 void ConvexHull() /** 基于水平的Andrew算法求凸包 */
42 {
43     sort(p,p+n,cmp); /**先按照 x 从小到大排序, 再按照 y 从小到大排序*/
44     m = 0;
45 
46     for(int i = 0; i < n; i++) /** 从前往后找 */
47     {
48         while(m > 1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--;
49         ch[m++] = p[i];
50     }
51     int k = m;
52     for(int i = n-2; i >= 0; i--) /**从后往前找, 形成完整的封闭背包*/
53     {
54         while(m > k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--;
55         ch[m++] = p[i];
56     }
57     if(n > 1) m--;
58 }
59 
60 int rotating_calipers() /**旋转卡壳模板*/
61 {
62     int q = 1;
63     int ans = 0;
64     ch[m] = ch[0]; /**凸包边界处理*/
65     for(int i = 0; i < m; i++) /**依次用叉积找出凸包每一条边对应的最高点*/
66     {
67         while(Cross(ch[i+1]-ch[i], ch[q+1]-ch[i]) > Cross(ch[i+1]-ch[i], ch[q]-ch[i]))
68             q = (q+1)%m;
69         ans = max(ans, max(squarDist(ch[i], ch[q]), squarDist(ch[i+1], ch[q+1])));
70     }
71     return ans;
72 }
73 
74 int main()
75 {
76     while(scanf("%d", &n) != EOF)
77     {
78         if(n == 0) break;
79         for(int i = 0; i < n; i++)
80             scanf("%lf%lf", &p[i].x, &p[i].y);
81 
82         ConvexHull();
83 
84         printf("%.8lf\n", sqrt(rotating_calipers()));
85     }
86     return 0;
87 }
View Code

 

 

同学用结构体 + 遍历凸包也可以解决。

 

AC代码:

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<math.h>
 4 using namespace std;
 5 struct point
 6 {
 7     int x;
 8     int y;
 9 }p[100005],res[100005];
10 int cmp(point p1,point p2)
11 {
12     return p1.y<p2.y||(p1.x==p2.x&&p1.x<p2.x);
13 }
14 bool ral(point p1,point p2,point p3)
15 {
16     return (p2.x-p1.x)*(p3.y-p1.y)>(p3.x-p1.x)*(p2.y-p1.y);
17 }
18 int main()
19 {
20     int n,i,j;
21     while((scanf("%d",&n))!=EOF)
22     {
23         for(i=0;i<n;i++)
24             scanf("%d %d",&p[i].x,&p[i].y);
25         sort(p,p+n,cmp);
26         res[0]=p[0];
27         res[1]=p[1];
28         int top=1;
29         for(i=2;i<n;i++)
30         {
31             while(top&&!ral(res[top],res[top-1],p[i]))
32                 top--;
33             res[++top]=p[i];
34         }
35         int len=top;
36         res[++top]=p[n-2];
37         for(i=n-3;i>=0;i--)
38         {
39             while(top!=len&&!ral(res[top],res[top-1],p[i]))
40                 top--;
41             res[++top]=p[i];
42         }
43         double maxx=0;
44         for(i=0;i<top;i++)
45         {
46             for(j=i+1;j<top;j++)
47             {
48                 double s=(res[i].x-res[j].x)*(res[i].x-res[j].x)+(res[i].y-res[j].y)*(res[i].y-res[j].y);
49                 if(s>maxx)
50                     maxx=s;
51             
52             }
53         }
54         printf("%.8lf\n",sqrt(maxx));
55     }
56     return 0;
57 }
View Code

 

你可能感兴趣的:(OO)