經典的求凸包題,模闆題。
要求用資源最少,那肯定這個多邊形是個凸多邊形,也就是凸包。
是以先求出凸包,計算它的周長。還有就是這道題所說的,要離城牆L遠,其實就是在加上一個圓的周長,圓的半徑就是L。
都說到這了,這道題還差什麼?還差一個經典的凸包模闆!哈哈~
代碼如下:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define eps 1e-8
#define MAX 1111
#define pi acos(-1.0)
using namespace std;
struct Point
{
double x,y;
Point(double x=0,double y=0):x(x),y(y) {}
};
Point point[MAX];
Point ch[MAX];
int N,L;
double ans;
typedef Point Vector;
Vector operator + (Vector A, Vector B) {return Vector(A.x+B.x,A.y+B.y);}
Vector operator - (Point A, Point B) {return Vector(A.x-B.x,A.y-B.y);}
Vector operator * (Vector A, double p) {return Vector(A.x*p,A.y*p);}
Vector operator / (Vector A, double p) {return Vector(A.x/p,A.y/p);}
bool operator < (const Point &a,const Point &b) {return a.x<b.x||(a.x==b.x&&a.y<b.y);}
int dcmp(double x)
{
if(fabs(x)<eps) return 0;
else return x<0?-1:1;
}
bool operator ==(const Point& a,const Point& b)
{
return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
double Dot(Vector A,Vector B) {return A.x*B.x+A.y*B.y;} //點積
double Length(Vector A) {return sqrt(Dot(A,A));} //向量長度
double Angle(Vector A,Vector B) {return acos(Dot(A,B)/Length(A)/Length(B));} //向量夾角
double Cross(Vector A,Vector B) {return A.x*B.y-A.y*B.x;} //叉積
//計算凸包,出入點數組p,個數為p,輸出點數組ch,函數傳回凸包頂點數。
//輸入不能有重複點。函數執行完之後輸入點的順序被破壞
//如果不希望在凸包的邊上有輸入點,把兩個<=改成<
//在精度要求高的時候,用dcmp比較
int ConvexHull(Point *p,int n)
{
sort(p,p+n);
int m=0;
for(int i=0;i<n;i++)
{
while(m>1&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
ch[m++]=p[i];
}
int k=m;
for(int i=n-2;i>=0;i--)
{
while(m>k&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
ch[m++]=p[i];
}
if(n>1) m--;
return m;
}
void input()
{
int i,j;
for(i=0;i<N;i++)
{
scanf("%lf%lf",&point[i].x,&point[i].y);
}
}
double cal(int n)
{
int i,j;
ch[n]=ch[0];
double len=0.0;
for(i=1;i<=n;i++)
{
len+=Length(ch[i]-ch[i-1]);
}
len+=2*pi*L;
return len;
}
int main()
{
int i,j,num;
scanf("%d%d",&N,&L);
input();
num=ConvexHull(point,N);
ans=cal(num);
printf("%0.0lf\n",ans);
return 0;
}