Address:http://poj.org/problem?id=1113
题目意思: 本题目给你N,L,N代表有这个城堡有N个点组成,L是你现在建的墙离城堡的最小距离。 题解 :求出凸包 凸包的周长 加上 以L 为半径的圆周长
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
struct point
{
double x, y;
}pnt[1010],res[1010];
double dis(point a,point b) {
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool mult(point sp, point ep, point op){
return (sp.x - op.x) * (ep.y - op.y)>= (ep.x - op.x) * (sp.y - op.y);
}
bool operator < (const point &l, const point &r){
return l.y < r.y || (l.y == r.y && l.x < r.x);
}
int graham(int n)
{
int i, len, k = 0, top = 1;
sort(pnt, pnt + n);
if (n == 0) return 0; res[0] = pnt[0];
if (n == 1) return 1; res[1] = pnt[1];
if (n == 2) return 2; res[2] = pnt[2];
for (i = 2; i < n; i++) {
while (top && mult(pnt[i], res[top], res[top-1]))
top--;
res[++top] = pnt[i];
}
len = top; res[++top] = pnt[n - 2];
for (i = n - 3; i >= 0; i--)
{
while (top!=len && mult(pnt[i], res[top],res[top-1]))
top--;
res[++top] = pnt[i];
}
return top;
}
int main()
{
int n,i;
double L;
while(cin>>n>>L)
{
for(i=0;i<n;i++)
cin>>pnt[i].x>>pnt[i].y;
int top=graham(n);
res[top]=res[0];
double sum=0;
for(i=0;i<top;i++)
sum+=dis(res[i],res[i+1]);
sum+=2*PI*L;
sum+=0.5;
cout<<(int)sum<<endl;
}
return 0;
}
这个代码 时间上有点长。
下面看了一大牛的。
16MS
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstdlib>
using namespace std;
#define eps 1e-8
#define MAXN 1010
#define INF 1<<30
#define PI 3.1415926
#define zero(x) (((x)>0?(x):-(x)) < eps)
struct point
{
int x,y;
};
point p[MAXN];
int astack[MAXN];
int cnt;
int xmult(point p1,point p2,point p0)
{
return (p1.x - p0.x) * (p2.y - p0.y) - (p1.y - p0.y) * (p2.x - p0.x);
}
int dis(point p1,point p2)
{
// cout<<(p1.x - p2.x) * (p1.x - p2.x)<<' ';
//cout<<(p1.y - p2.y) * (p1.y - p2.y)<<endl;
return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);
}
bool cmp(const point &a,const point &b)
{
int temp = xmult(a,b,p[0]);
if (temp > eps)
return true;
if (zero(temp) && (dis(a,p[0])) < (dis(b,p[0])))
return true;
return false;
}
//极角排序
void Graham(point p[],int n)
{
int lowpos = 0,minvalue = INF;
int i;
for(i = 1;i < n;++i)
{
if(p[lowpos].x >= p[i].y && p[lowpos].y >= p[i].y)
lowpos = i;
}
swap(p[0],p[lowpos]);
sort(p+1,p+n,cmp);
//用栈去存当前凸包的顶点
astack[0] = 0;
astack[1] = 1;
cnt = 1;
for(i = 2;i < n;++i)
{
//在左边,直接放去栈中
//cout<<(xmult(p[i],p[astack[cnt]],p[astack[cnt-1]]))<<endl;
if ((xmult(p[i],p[astack[cnt]],p[astack[cnt-1]])) <= 0 )
astack[++cnt] = i;
else
{
do
{
cnt--;
}while(xmult(p[i],p[astack[cnt]],p[astack[cnt-1]]) > 0);
astack[++cnt] = i;
}
}
}
int main ()
{
int n,l,i;
scanf("%d%d",&n,&l);
for(i = 0;i < n;++i)
scanf("%d%d",&p[i].x,&p[i].y);
Graham(p,n);
//for(int i = 0;i <= cnt;++i)
//printf("%d %d\n",p[astack[i]].x,p[astack[i]].y);
double sum = 0;
for(i = 0;i < cnt;++i)
{
sum += sqrt(dis(p[astack[i]],p[(astack[i+1])]) * 1.0);
//printf("%lf\n",sum);
}
sum += sqrt(dis(p[astack[0]],p[astack[cnt]])*1.0);
//printf("%lf\n",sum);
sum += PI* 2 * l+0.5;
printf("%d\n",(int)sum);
return 0;
}