POJ

原题链接

模板题,直接说思路。

思路:

要求一距离凸包为 L 的图形的周长,即为 凸包周长+L为半径的圆周长 ,直接用 Graham 求一次凸包即可。

  1 /*
  2 * @Author: windystreet
  3 * @Date:   2018-08-02 20:41:25
  4 * @Last Modified by:   windystreet
  5 * @Last Modified time: 2018-08-02 22:30:59
  6 */
  7 #include <stdio.h>
  8 #include <math.h>
  9 #include <string.h>
 10 #include <algorithm>
 11 using namespace std;
 12 
 13 #define X first
 14 #define Y second
 15 #define eps  1e-2
 16 #define gcd __gcd
 17 #define pb push_back
 18 #define PI acos(-1.0)
 19 #define lowbit(x) (x)&(-x)
 20 #define bug printf("!!!!!
");
 21 #define mem(x,y) memset(x,y,sizeof(x))
 22 
 23 typedef long long LL;
 24 typedef long double LD;
 25 typedef pair<int,int> pii;
 26 typedef unsigned long long uLL;
 27 
 28 const int maxn = 1e3+2;
 29 const int INF  = 1<<30;
 30 const int mod  = 1e9+7;
 31 
 32 struct point
 33 {
 34     int x,y;
 35     point (){}
 36     point(int _x,int _y){
 37         x = _x;y = _y;
 38     }
 39     point operator - (const point &b)const{                  // 定义减法
 40         return point(x-b.x,y-b.y);
 41     }
 42     int operator ^ (const point &b)const{                    // 定义叉积
 43         return x*b.y - y*b.x;
 44     }
 45 };
 46 point List[maxn];
 47 int Stack[maxn],top;
 48 
 49 double dis(point p1,point p2){
 50     return sqrt((double)((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)));
 51 }
 52 bool cmp(point p1,point p2){                                // 极角排序
 53     int tmp = (p1-List[0])^(p2-List[0]);
 54     if(tmp>0)return true;
 55     else if(tmp==0 && (dis(List[0],p1)<dis(List[0],p2))) return true;
 56     else return false;
 57 }
 58 void Graham(int n){
 59     point p0;
 60     int k = 0;
 61     p0 = List[0];
 62     for(int i=1;i<n;i++){
 63         if((p0.y > List[i].y)||(p0.y == List[i].y && p0.x > List[i].x)){
 64             p0 = List[i]; k = i;
 65         }
 66     }
 67     swap(List[k],List[0]);
 68     sort(List+1,List+n,cmp);
 69     if(n==1){
 70         top = 0;Stack[0] = 0; return ;
 71     }else if(n==2){
 72         top = 1;Stack[0] = 0;Stack[1] = 1;return;
 73     }
 74     Stack[0] = 0;Stack[1] = 1;top = 1;
 75     for(int i = 2 ;i < n; i++){
 76         while(top > 0 && ((List[Stack[top]]-List[Stack[top-1]])^(List[i]-List[Stack[top-1]]))<=0)top--;
 77         Stack[++top] = i;
 78 
 79     }
 80 }
 81 
 82 void solve(){
 83     int n,L;
 84     while(~scanf("%d%d",&n,&L)){
 85         double ans = 0;
 86         for(int i=0;i<n;i++){
 87             scanf("%d%d",&List[i].x,&List[i].y);
 88         }
 89         Graham(n);
 90         for(int i=0;i<top;i++){
 91             ans += dis(List[Stack[i]],List[Stack[i+1]]);
 92         }
 93         ans += dis(List[Stack[0]],List[Stack[top]]);            // 计算凸包周长
 94         ans += PI*L*2.0;                                        // 加上一个圆的周长
 95         printf("%d
",(int)(ans+0.5));                            // 答案四舍五入
 96     }
 97     return;
 98 }
 99 
100 int main()
101 {
102 //    freopen("in.txt","r",stdin);
103 //    freopen("out.txt","w",stdout);
104 //    ios::sync_with_stdio(false);
105     int t = 1;
106     while(t--){
107     //    printf("Case %d: ",cas++);
108         solve();
109     }
110     return 0;
111 }
原文地址:https://www.cnblogs.com/windystreet/p/9410736.html