模板题,直接说思路。
思路:
要求一距离凸包为 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 }