地址:http://acm.bit.edu.cn/mod/programming/view.php?a=522
做过好几遍的题。。答案等于凸包周长+半径为l的圆的周长。n=1,2特判下就行。。
WA了无数次。。全改double就过了
#include <iostream>
#include <cmath>
#include <algorithm>
#define PI acos(-1.0)
using namespace std;
int n,l;
int top;
struct point
{
int x,y;
}p[100005],stack[100005];
double dis0(point a,point b)
{
return sqrt((double)((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)));
}
double chaji(point a,point b,point c) //BA*CA
{
return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
bool cmp(point a,point b)
{
int ans;
ans=chaji(p[0],a,b);
if(ans>0) return true;
else if(ans==0&&dis0(a,p[0])<dis0(b,p[0])) return true;
return false;
}
void graham()
{
int i;
top=0;
stack[top++]=p[0],stack[top++]=p[1],stack[top++]=p[2];
for(i=3;i<n;stack[top++]=p[i++])
{
while(top>=2&&chaji(stack[top-2],stack[top-1],p[i])<0) top--;
}
}
int main()
{
point temp;
double res;
int i;
int min;
int ni;
while(scanf("%d%d",&n,&l)!=EOF)
{
min=2000000000;
for(i=0;i<n;i++)
{
scanf("%d%d",&p[i].x,&p[i].y);
if(min>p[i].x) min=p[i].x,ni=i;
else if(min==p[i].x&&p[ni].y<p[i].y) ni=i;
}
if(n==1)
{
printf("%.2lf\n",2*PI*l);
continue;
}
if(n==2)
{
res=dis0(p[0],p[1]);
printf("%.2lf\n",res*2+2*PI*l);
continue;
}
temp=p[0],p[0]=p[ni],p[ni]=temp;
sort(p+1,p+n,cmp);
graham();
res=0;
for(i=0;i<top-1;i++)
{
res+=dis0(stack[i],stack[i+1]);
}
res+=dis0(stack[top-1],stack[0]);
res+=2*PI*l;
printf("%.2lf\n",res);
}
return 0;
}