zoukankan      html  css  js  c++  java
  • 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

    Input

    Output

    Sample Input

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

    Sample Output

    316.86590223

    HINT

    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
    ", 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
    ",sqrt(maxx));
    55     }
    56     return 0;
    57 }
    View Code
  • 相关阅读:
    Bash Shell 快捷键
    vector-swap
    vector-swap
    vector-size
    Android网络篇
    应用 Valgrind 发现 Linux 程序的内存问题
    树莓派初学者?先做做这十个项目吧
    树莓派 (为学习计算机编程教育设计的一种微型电脑)
    微软windows10 IOT支持PI3之后,树莓派3更是将获得Android官方原生支持
    Linux基金会宣布JS Foundation基金会成立 前身为jQuery团队
  • 原文地址:https://www.cnblogs.com/jeff-wgc/p/4474778.html
Copyright © 2011-2022 走看看