Wall
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1348
题意:给定多边形城堡的n个顶点,绕城堡外面建一个围墙,围住所有点,并且墙与所有点的距离至少为L,求这个墙最小的长度。
思路:如果没有"墙与所有点的距离至少为L"这个条件就只要求一个凸包,再求凸包的周长即可。墙与所有点的距离至少为L,其实只要在凸包的周长上再加一个半径为L的圆周长即可。
在vj上一直过不了,杭电oj就能过。吐了。
#include<bits/stdc++.h> #include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<map> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const double PI = atan(1.0)*4.; const int maxn=200005; struct point { double x,y; point friend operator -(point A,point B) { return {A.x-B.x,A.y-B.y}; } }; struct line { point x,y; }; point p[maxn];//输入点集 point q[maxn];//凸包点集 double dis(point A,point B)//两点的距离 { return sqrt( (A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y) ); } double chaj(point A,point B)//差积 { return A.x*B.y-A.y*B.x; } bool cmp(point A,point B)//以p[0]为起点,按差积逆时针排序 { double s=chaj(A-p[1],B-p[1]); if(s>0) return true; if(s==0) return dis(A,p[1])<dis(B,p[1]); return false; } double perimeter(int len)//凸包求周长 { double sum=0; for(int i=2; i<=len; i++) sum+=dis(q[i-1],q[i]); return sum+dis(q[1],q[len]); } int main() { int t,u=0; cin>>t; while(t--) { if(u>0) cout<<endl; u++; int N,M; cin>>N>>M; for(int i=1; i<=N; i++) cin>>p[i].x>>p[i].y; //找到最小的点 int K=1; for(int i=2; i<=N; i++) { if(p[i].y<p[K].y||(p[i].y==p[K].y&&p[i].x<p[K].x)) K=i; } swap(p[1],p[K]); sort(p+2,p+1+N,cmp); q[1]=p[1]; q[2]=p[2]; int len=2;//凸包点的个数 for(int i=3; i<=N; i++) { while(len>=2&&chaj(q[len]-q[len-1],p[i]-q[len-1])<=0) len--; q[++len]=p[i]; } double sum=2*M*PI; printf("%.lf\n",perimeter(len)+sum);//周长 } }