pku 1113 Wall 凸包
http://poj.org/problem?id=1113
题意是给定一个城堡的各个点,然你求出设计一个城墙,包围这个城堡并且保证城墙距离城堡必须大于等于一个给定的距离:
首先是利用图报求出最小的包围城堡的凸多边形,然后求出距离,然后再加上一个整圆就OK了,圆的半径就是给定的距离:(整个思路相当于把凸多边形各个边往外移动距离R,此后连接各边的弧组成一个以R为半径的整圆);
到此终于把POJ计划的初级阶段刷完了...纪念一下。。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> using namespace std; const double eps = 1e-8; const int maxn = 1007; const double pi = acos(-1.0); struct point { double x,y; }pt[maxn],stack[maxn]; int top; int cmp(point a,point b) { if (a.y != b.y) return a.y < b.y; else return a.x < b.x; } int dblcmp(double x) { if (x > eps) return 1; else if (x < -eps) return -1; else return 0; } double det(double x1,double y1,double x2,double y2) { return x1*y2 - x2*y1; } double cross(point a,point b,point c) { return det(b.x - a.x,b.y - a.y,c.x - a.x,c.y - a.y); } //这里起点与终点肯定在凸包上,不知道怎么证明 int graham(point *p,int len) { top = 0; int i; //先排序,lrj黑书上的排序方法 sort(p,p + len,cmp); stack[top++] = p[0]; stack[top++] = p[1]; //求右链 for (i = 2; i < len; ++i) { while (top > 1 && dblcmp(cross(stack[top - 2],stack[top - 1],p[i])) <= 0) top--; stack[top++] = p[i]; } //求左链 int tmp = top; for (i =len - 2; i >= 0; --i) { while (top > tmp && dblcmp(cross(stack[top - 2],stack[top - 1],p[i]))<= 0) top--; stack[top++] = p[i]; } return top - 1;//起点两次进栈 - 1 } double dis(point a,point b) { double x = a.x - b.x; double y = a.y - b.y; return sqrt(x*x + y*y); } int main() { int n,i,r; scanf("%d%d",&n,&r); for (i = 0; i < n; ++i) scanf("%lf%lf",&pt[i].x,&pt[i].y); int len = graham(pt,n); double L = 0; for (i = 0; i < len; ++i) L += dis(stack[i],stack[(i + 1)%len]); L = L + 2.0*pi*r; printf("%.0lf\n",L); return 0; }