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;
}

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值