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;

}

  

你可能感兴趣的:(pku)