原題連接:http://poj.org/problem?id=1113
題意:給 n 個點,你見一個圍牆,使所有的點到圍牆的距離不小於 l 。求圍牆長度。。
思路:先求出n個點的 凸包,然後根據凸包建一個圍牆,圍牆的一部分就是 凸包長度,另一部分 是一個 以 l 爲半徑的 圓!!
代碼:
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
int m,top;
struct point
{
int x,y;
}P[2000],S[2000],T;
void find_pole_point() //找到基點 交換到 0
{
int i,j=0;
T=P[0];
for(i=1;i<m;i++)
{
if(P[i].y<T.y||(P[i].y==T.y&&P[i].x<T.x))
{
j=i;
T=P[i];
}
}
T=P[0];
P[0]=P[j];
P[j]=T;
}
double dis(point t1,point t2) //計算兩點距離
{
double z=(t1.x-t2.x)*(t1.x-t2.x)+(t1.y-t2.y)*(t1.y-t2.y);
return sqrt(z);
}
double cross(point t1,point t2,point t3,point t4) //向量叉積
{
return (t2.x-t1.x)*(t4.y-t3.y)-(t2.y-t1.y)*(t4.x-t3.x);
}
bool cmp(point t1,point t2)
{
double z= cross(P[0],t1,P[0],t2);
return z? z>0:dis(P[0],t1)>dis(P[0],t2);
}
void scanner() //求凸包
{
int i,j;
find_pole_point();
sort(P+1,P+m,cmp);
S[0]=P[0];
S[1]=P[1];
top=1;
for(i=2;i<m;i++)
{
while(cross(S[top-1],S[top],S[top],P[i])<0)
top--;
top++;
S[top]=P[i];
}
}
int main()
{
int i,j,ncase,l;
while(scanf("%d%d",&m,&l)!=EOF)
{
for(i=0;i<m;i++)
scanf("%d%d",&P[i].x,&P[i].y);
scanner();
double ans= 2*3.1415926*l;
for(i=0;i<=top;i++)
ans+= dis(S[i],S[(i+1)%(top+1)]);
printf("%.0lf\n",ans);
}
}