wall poj 1113

题目链接:http://poj.org/problem?id=1113

题意:一个国王要在自己的城堡周围建一堵围墙,要求围墙距城堡最短距离为L。问建这样一堵围墙的最短长度是多少。

 

题解思路:显然围墙建的距城堡越近越好,这样对于城堡的边我们沿着城堡距离L的地方建就可以了,对于城堡的顶点,我们以顶点为圆心,以L为半径画一段圆弧。易之围墙的周长即为圆弧和+沿城堡建的围墙的和。

但题目并没说给的多变形就是凸多边形。显然如果是凸多边形的话,直接用上面的方法计算即可。而对于凹多边形凹的部分如果我们也像上面的做法那样沿着城堡的边建围墙,顶点画圆弧,然后两者再加起来的话显然是错误的,因为我们知道两点之间直线最短,这样做得到的边长和显然要大于两点间的直线段的和!所以对于凹多边形,我们的做法是用一条线段直接将凹下去两点连起来,使之成为一个凸包。所以这样题目就很简单了,直接用扫描法构造凸包,将其中凹下去的部分舍掉即可。

 

还有一点,凸多边形的外角和等于360度,所以所有圆弧的部分加起来就是一个园。所以最后围墙的最短周长就是:构造的凸多边形的周长+半径为L的园的周长。

 

此题题目有点误导人,题意已经指出城堡的顶点以顺时针给出,但实际的数据并不是按序给出的!所以先要自己排好序,再构建凸包。(有点坑爹。。。害我WA了好几次。。。)

AC 代码:

View Code
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 using namespace std;
 6 #define pi acos(-1)
 7 #define eps 1e-8 
 8 using namespace std;
 9 const int N=1005;
10 struct point{
11     double x,y;
12 }pt[N];
13 int con[N];
14 int n,l,tot;
15 double dist(point a,point b){
16     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
17 }
18 double xmult(point p0,point p1,point p2){
19     double x1=p1.x-p0.x;
20     double y1=p1.y-p0.y;
21     double x2=p2.x-p0.x;
22     double y2=p2.y-p0.y;
23     return (x1*y2-x2*y1);
24 }
25 bool cmp(point a,point b){
26     if(xmult(pt[0],a,b)>0||xmult(pt[0],a,b)==0&&(dist(a,pt[0])<dist(b,pt[0])))return true;
27     return false;
28 }
29 void graham(){
30     sort(pt+1,pt+n,cmp);
31     tot=0;
32     con[tot++]=0;
33     con[tot++]=1;
34     for(int i=2;i<n;){
35         if(tot<1||xmult(pt[con[tot-2]],pt[con[tot-1]],pt[i])>=0)
36             con[tot++]=i++;
37         else tot--;
38     }
39     con[tot]=0;
40 }
41 int main()
42 {
43     //freopen("in.txt","r",stdin);
44     int i,k;
45     double ans;
46     while(scanf("%d %d",&n,&l)!=EOF){
47         k=n-1;
48         for(i=n-1;i>=0;i--){
49             scanf("%lf %lf",&pt[i].x,&pt[i].y);
50             if(pt[i].y<pt[k].y||((pt[i].y==pt[k].y)&&(pt[i].x<pt[k].x)))
51                     k=i;
52         }
53         if(k){
54             swap(pt[0].x,pt[k].x);
55             swap(pt[0].y,pt[k].y);
56         }
57         graham();
58         ans=0;
59         for(i=0;i<tot;i++)
60             ans+=dist(pt[con[i]],pt[con[i+1]]);
61         ans+=2*pi*l;
62         printf("%d\n",(int)(ans+0.5));
63     }
64     return 0;
65 }

 

 

posted on 2012-09-04 15:55  Acmer_Roney  阅读(163)  评论(0)    收藏  举报

导航