Poj1113
有这么一个城堡,它的俯视平面图由一堆柱子组成(不要问我为什么),然后问这个城堡最小需要的围墙长度。
解:画个图就比较清楚了,去掉所有圆弧,将剩余边进行平移,恭喜你一个凸包就在你眼前。接下来的问题就完全是数学问题了,我选择用水平序算法去求凸包。
水平序算法实际上就是做两遍凸壳,拼在一起就是个包了。
听起来很简单对不对,可是我还就是写错了。
第一遍写水平序忽视了队列为空是不能弹出元素的。Orz..
解决方法:l=0;r=-1; (l<=r)的情况下队列为空。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define eps 1e-10
#define MAXN 1005
const double Pi=acos(-1.0);
using namespace std;
struct point{
double x,y;
point(){x=y=0;}
point(double _x,double _y){x=_x;y=_y;}
}T[MAXN];
int Q[MAXN*2];
bool cmp(point a,point b){return a.x==b.x?a.y<b.y:a.x<b.x;}
point V(point start,point end){return point(end.x-start.x,end.y-start.y);}
double Cross(point a,point b){return a.x*b.y-b.x*a.y;}
double dis(point a,point b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
int n;double L;
int main(){
double ans=0;int l,r;
scanf("%d%lf",&n,&L);
for(int i=1;i<=n;i++) scanf("%lf%lf",&T[i].x,&T[i].y);
sort(T+1,T+n+1,cmp);
l=0,r=-1;
for(int i=1;i<=n;i++){
while(l<r&&Cross(V(T[Q[r-1]],T[Q[r]]),V(T[Q[r]],T[i]))>eps) r--;
Q[++r]=i;
}
for(int i=l;i<r;i++) ans+=dis(T[Q[i]],T[Q[i+1]]);
memset(Q,0,sizeof(Q));
l=0,r=-1;
for(int i=n;i>=1;i--){
while(l<r&&Cross(V(T[Q[r-1]],T[Q[r]]),V(T[Q[r]],T[i]))>eps) r--;
Q[++r]=i;
}for(int i=l;i<r;i++) ans+=dis(T[Q[i]],T[Q[i+1]]);
ans+=2*L*Pi;
printf("%d\n",(int)(ans+0.5));
return 0;
}