Poj 1113--Wall(凸集)

Wall

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 33446   Accepted: 11376

Description

Once upon a time there was a greedy King who ordered his chief Architect to build a wall around the King‘s castle. The King was so greedy, that he would not listen to his Architect‘s proposals to build a beautiful brick wall with a perfect shape and nice tall towers. Instead, he ordered to build the wall around the whole castle using the least amount of stone and labor, but demanded that the wall should not come closer to the castle than a certain distance. If the King finds that the Architect has used more resources to build the wall than it was absolutely necessary to satisfy those requirements, then the Architect will loose his head. Moreover, he demanded Architect to introduce at once a plan of the wall listing the exact amount of resources that are needed to build the wall. 

Your task is to help poor Architect to save his head, by writing a program that will find the minimum possible length of the wall that he could build around the castle to satisfy King‘s requirements.

The task is somewhat simplified by the fact, that the King‘s castle has a polygonal shape and is situated on a flat ground. The Architect has already established a Cartesian coordinate system and has precisely measured the coordinates of all castle‘s vertices in feet.

Input

The first line of the input file contains two integer numbers N and L separated by a space. N (3 <= N <= 1000) is the number of vertices in the King‘s castle, and L (1 <= L <= 1000) is the minimal number of feet that King allows for the wall to come close to the castle.

Next N lines describe coordinates of castle‘s vertices in a clockwise order. Each line contains two integer numbers Xi and Yi separated by a space (-10000 <= Xi, Yi <= 10000) that represent the coordinates of ith vertex. All vertices are different and the sides of the castle do not intersect anywhere except for vertices.

Output

Write to the output file the single number that represents the minimal possible length of the wall in feet that could be built around the castle to satisfy King‘s requirements. You must present the integer number of feet to the King, because the floating numbers are not invented yet. However, you must round the result in such a way, that it is accurate to 8 inches (1 foot is equal to 12 inches), since the King will not tolerate larger error in the estimates.

Sample Input

9 100
200 400
300 400
300 300
400 300
400 400
500 400
500 200
350 200
200 200

Sample Output

1628

Hint

结果四舍五入就可以了

Source

Northeastern Europe 2001

据题意可得: 所求结果为凸包周长+ 2*PI* L ;

转个分析:

证明如下:假如顺时针给出四个点A、B、C、D。组成了凸四边形ABCD。我们不妨过A点作AE垂直于AB,同时过A点再作AF垂直于AD,过B点作BG、BH分别垂直于AB、BC。连结EG,垂线段的长度为L,过A点以AE为半径作一段弧连到AF,同理,使GH成为一段弧。此时EG=AB(边),AB段城墙的最小值为EF+弧EF+弧GH=AB+弧EF+弧GH。对所有点进行同样的操作后,可知城墙的最小值=四边形的周长+相应顶点的弧长(半径都为L)之和。

下面证明这些顶点弧长组成一个圆。依然以前面的四边形为例。A、B、C、D四顶点各成周角,总和为360*4=1440度,四边形内角和为360度,每个顶点作两条垂线,总角度为4*2*90=720度,所以总圆周角为1440-360-720=360度,刚好组成圆。

所以四边形ABCD的围墙最短= 四边形的周长+圆周长。

推广到任意多边形,用同样的方法,城墙最短=凸包的周长 + 以L为半径的圆的周长。

首先,我们得出城墙最短=凸包的周长 + 相应顶点的弧长(半径都为L)之和。

再证明 相应顶点的弧长(半径都为L)之和=以L为半径的圆的周长。

事实上,设凸包顶点为n,n个顶点组成n个周角,角度为360*n=2*180*n,凸包的内角和为180*(n-2),作了2*n条垂线,和为2*n*90=180*n,所以总圆周角为2*180*n-180*(n-2)-180*n=360,组成圆。

#include <cmath>
#include <cstdio>
#define PI acos(-1.0)
#define MAXN 1001
#include <iostream>
#include <algorithm>
using namespace std;

struct point
{
    int x, y;
} ;
point list[MAXN];
int stack[MAXN], top;

int cross(point p0, point p1, point p2)  //叉乘,  p0p1 X p0p2;
{
    return (p1.x-p0.x)*(p2.y-p0.y) - (p1.y-p0.y)*(p2.x-p0.x);
}

double dis(point p1, point p2)
{
    return sqrt((double)(p2.x-p1.x)*(p2.x-p1.x) + (p2.y-p1.y)*(p2.y-p1.y));
}

bool cmp(point p1, point p2)    //极角排序,
{
    int tmp=cross(list[0], p1, p2);
    if(tmp > 0) return true;
    else if(tmp==0&& dis(list[0], p1) < dis(list[0], p2)) return true;
    else return false;
}

void init(int n)       //找出左下角的点放在list[0] 中 ;
{
    point fv;
    scanf("%d%d", &list[0].x, &list[0].y);
    fv.x= list[0].x;  fv.y=list[0].y;
    int k=0;
    for(int i=1; i<n; i++)
    {
        scanf("%d%d", &list[i].x, &list[i].y);
        if( (fv.y >list[i].y) || (fv.y==list[i].y && fv.x>list[i].x))
        {
            fv.x= list[i].x;
            fv.y =list[i].y;
            k=i;
        }
    }
    list[k]= list[0];
    list[0]=fv;

    sort(list+1, list+n, cmp) ;
}

void graham(int n)
{
    if(n==1) {top=0; stack[0]=0;}
    if(n==2) {top=1; stack[0]=0; stack[1]=1;}
    if(n >2)
    {
        for(int i=1; i<=1; i++)
            stack[i]=i;
        top=1;

        for(int i=2; i<n; i++)
        {
            while(top >0 && cross(list[stack[top-1]], list[stack[top]], list[i]) <= 0) top--;  //找最外围的点 ;
            top++;
            stack[top]= i;
        }
    }
}
int main()
{
    int N, L;
    while(scanf("%d%d", &N, &L) != EOF)
    {
        init(N);
        graham(N);
        double res= 0;
        for(int i=0; i<top; i++)
            res+= dis(list[stack[i]], list[stack[i+1]]);
        res +=dis(list[stack[0]], list[stack[top]]);
        res += 2*PI*L;
        //printf("%d\n", (int)(res+0.5));
        printf("%.lf\n", res );
    }
    return 0;
} 
时间: 2024-07-30 19:21:33

Poj 1113--Wall(凸集)的相关文章

G++和C++ &amp;&amp; POJ 1113 Wall

PS: 次题目虽然叙述点的个数大于等于3但是并不保证凸包是否存在,所以还要判断一下.经常刷题的孩纸可能会遇到用C++ 可用AC的题目用G++ 却 Wrong Answer. 思考过为什么吗? 对于double 类型用%lf 输入用%lf输出是window 环境下VC的标准但不是真正的标准,对于double 类型 真正的标准是用%lf输入,用%f输出.所以把%.0lf改为%.0f 在G++环境下面就可用轻松AC了. 还有%lld 和 %I64d, 同时也学习一下控制精度的技巧,比如 printf(

poj 1113 Wall (凸包模板题)

Wall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 32808   Accepted: 11137 Description Once upon a time there was a greedy King who ordered his chief Architect to build a wall around the King's castle. The King was so greedy, that he w

POJ 1113 Wall (凸包)

题目地址:POJ 1113 先求出凸包的周长,然后剩下的弧合起来一定是个半径为l的圆,然后再加上以l为半径的圆的周长即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <

poj 1113 Wall 凸包的应用

题目链接:poj 1113   单调链凸包小结 题解:本题用到的依然是凸包来求,最短的周长,只是多加了一个圆的长度而已,套用模板,就能搞定: AC代码: 1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cmath> 5 using namespace std; 6 int m,n; 7 struct p 8 { 9 double x,y; 10 friend i

POJ 1113 Wall 凸包 裸

LINK 题意:给出一个简单几何,问与其边距离长为L的几何图形的周长. 思路:求一个几何图形的最小外接几何,就是求凸包,距离为L相当于再多增加上一个圆的周长(因为只有四个角).看了黑书使用graham算法极角序求凸包会有点小问题,最好用水平序比较好.或者用Melkman算法 /** @Date : 2017-07-13 14:17:05 * @FileName: POJ 1113 极角序求凸包 基础凸包.cpp * @Platform: Windows * @Author : Lweleth (

poj 1113 Wall(标准的凸包果题)

题目链接:http://poj.org/problem?id=1113 Description Once upon a time there was a greedy King who ordered his chief Architect to build a wall around the King's castle. The King was so greedy, that he would not listen to his Architect's proposals to build

●POJ 1113 Wall

题链: http://poj.org/problem?id=1113 题解: 计算几何,凸包 题意:修一圈围墙把给出的点包围起来,且被包围的点距离围墙的距离不能小于L,求围墙最短为多少. 答案其实就是等于N个点的凸包的周长+半径为L的圆的周长. 代码: #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define

POJ - 1113 Wall (凸包)

http://poj.org/problem?id=1113 题意 求能包围城堡的最小周长,其中必须与城堡每个点相隔L. 分析 答案是凸包周长加上一个圆周长,即包围凸包的一个圆角多边形. 但那些圆角加起来为什么恰好是一个圆呢?每个圆角是以凸包对应的顶点为圆心,给定的L为半径,与相邻两条边的切点之间的一段圆弧. 每个圆弧的两条半径夹角与对应的凸包的内角互补.假设凸包有n条边,则所有圆弧角之和为180°*n-180°*(n-2)=360°.(凸边形内角和为(n-2)*180) 故,围墙周长为=n条平

POJ 1113 Wall 卷包裹法求凸包

Wall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 31199   Accepted: 10521 Description Once upon a time there was a greedy King who ordered his chief Architect to build a wall around the King's castle. The King was so greedy, that he w

POJ 1113 Wall

这个的题意是绕一圈使得圈上所有点到原来的点的距离都大于等于l.求最短周长. 平移一下,几何乱搞?发现这个弧线刚好是个圆. convexhull..这个我抄的版也不知道是什么算法但是好像靠谱.研究凸包的一个算法. #include<iostream>#include<cstdio>#include<cmath>#include<algorithm>using namespace std;struct point{ int x,y; point(int x=0,