【POJ 1113】 Wall (凸包)

【POJ 1113】 Wall

给n个点 连出一个凸包 然后在凸包外筑墙 要求墙与凸包每一处的距离都>=l 问需要建的最短的墙长

乍一看挺难 画画图就能看出来 凸包外建距离l的墙 其实就是在凸包每个顶点处 以顶点为圆心 做半径为l的弧 做到两侧半径与点的两边平行即可 然后把这些弧都用直线衔接 就是最短墙长

这样还不好求 呢把弧拿出来呢 其实就相当于把整个凸包作为一个点 以该点为圆心 l为半径做了个圆 这样弧的总长就是2*PI*l 那剩下的就是直线 平移下来其实就是凸包的周长

然后卷包裹法或者扫描法都能过 毕竟数据弱

代码如下:

//卷包裹法
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define PI 3.141592653589793

using namespace std;

typedef struct Point
{
    int x,y;
    double operator - (const struct Point a)const
    {
        return sqrt((x-a.x)*(x-a.x) + (y-a.y)*(y-a.y));
    }
}Point;

typedef struct Line
{
    int x,y;
    bool operator > (const struct Line a)const//顺时针
    {
        return x*a.y - y*a.x > 0;
    }
    bool operator < (const struct Line a)const//逆时针
    {
        return x*a.y - y*a.x < 0;
    }
}Line;

Point pt[1000];

int main()
{
    int n,l,i;
    double len;
    int mp,tmp,mx;

    mp = 0;
    scanf("%d %d",&n,&l);
    for(i = 0; i < n; ++i)//输入 同时找到最左最下
    {
        scanf("%d %d",&pt[i].x,&pt[i].y);
        if(pt[i].x < pt[mp].x || (pt[i].x == pt[mp].x && pt[i].y < pt[mp].y))
            mp = i;
    }

    len = 2*PI*l;
    Line l1,l2;
    tmp = mp;//以最左最下的点为起点

    do//枚举每一个点 直到枚举完
    {
        mx = !tmp;
        for(i = 0; i < n; ++i)
        {
            l1.x = pt[mx].x - pt[tmp].x;
            l1.y = pt[mx].y - pt[tmp].y;
            l2.x = pt[i].x - pt[tmp].x;
            l2.y = pt[i].y - pt[tmp].y;
            if(l2 > l1 || (!(l2 < l1) && pt[i]-pt[tmp] > pt[mx]-pt[tmp]))//找出极角最大并且距离前一点最远的点
                mx = i;
        }
        len += pt[mx]-pt[tmp];//每找出一个凸包上的点就加一条边
        tmp = mx;
    }while(tmp != mp);//找回原点时凸包就建好了

    printf("%.0f\n",len);
    return 0;
}
//扫描法
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <stack>
#include <algorithm>
#define PI 3.141592653589793

using namespace std;

int xx,yy;

typedef struct Point
{
    int x,y;
    double operator - (const struct Point a)const
    {
        return sqrt((x-a.x)*(x-a.x) *1.0+ (y-a.y)*(y-a.y)*1.0);
    }

    bool operator < (const struct Point a)const
    {
        if(x == xx && y == yy) return false;
        if (a.x == xx && a.y == yy) return true;
        if((x-xx)*(a.y-yy) - (y-yy)*(a.x-xx) == 0) return sqrt((x-xx)*(x-xx) *1.0+ (y-yy)*(y-yy)*1.0) < sqrt((a.x-xx)*(a.x-xx) *1.0+ (a.y-yy)*(a.y-yy)*1.0);
        return (x-xx)*(a.y-yy) - (y-yy)*(a.x-xx) > 0;
    }
}Point;

typedef struct Line
{
    int x,y;
    bool operator < (const struct Line a)const//逆时针
    {
        return x*a.y - y*a.x < 0;
    }
}Line;

Point pt[1000];
stack <Point> s;

void SetTb(int n)//建凸包
{
    Line l1,l2;
    Point p1,p2;
    s.push(Point{xx,yy});
    s.push(pt[0]);

    for(int i = 1; i < n; ++i)
    {
        p1 = s.top();
        s.pop();
        while(!s.empty())
        {
            p2 = s.top();
            s.pop();
            l1.x = pt[i].x - p2.x;
            l1.y = pt[i].y - p2.y;
            l2.x = p1.x - p2.x;
            l2.y = p1.y-p2.y;
            if(l1 < l2)
            {
                s.push(p2);
                break;
            }
            p1 = p2;
        }
        s.push(p1);
        s.push(pt[i]);
    }
}

double Getlen()//从栈中不断出栈求凸包周长
{
    Point p1,p2;
    double len = 0;
    p2 = s.top();
    s.pop();
    while(!s.empty())
    {
        p1 = s.top();
        s.pop();
        len += p2-p1;
        p2 = p1;
    }
    return len;
}

void Read(int &n,int &l)//输入并进行极角排序
{
    int mp = 0;
    scanf("%d %d",&n,&l);
    for(int i = 0; i < n; ++i)
    {
        scanf("%d %d",&pt[i].x,&pt[i].y);
        if(pt[i].x < pt[mp].x || (pt[i].x == pt[mp].x && pt[i].y < pt[mp].y))
            mp = i;
    }
    xx = pt[mp].x,yy = pt[mp].y;
}

int main()
{
    int n,l,i;
    double len;
    Read(n,l);
    len = 2*PI*l;
    sort(pt,pt+n);
    SetTb(n);
    len += Getlen();
    printf("%.0f\n",len);
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-10 10:25:15

【POJ 1113】 Wall (凸包)的相关文章

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 凸包模板

此题为凸包问题模板题,题目中所给点均为整点,考虑到数据范围问题求norm()时先转换成double了,把norm()那句改成<vector>压栈即可求得凸包. 初次提交被坑得很惨,在GDB中可以完美运行A掉,到OJ上就频频RE(此处应有黑人问号) 后来发现了问题,原因是玩杂耍写了这样的代码 struct point { int x, y; point (){ scanf("%d%d", &x, &y); } ... }pt[MAXN]; 于是乎,在swap

POJ - 1113 Wall (凸包模板题)

原题链接 模板题,直接说思路. 思路: 要求一距离凸包为 L 的图形的周长,即为 凸包周长+L为半径的圆周长 ,直接用 Graham 求一次凸包即可. 1 /* 2 * @Author: windystreet 3 * @Date: 2018-08-02 20:41:25 4 * @Last Modified by: windystreet 5 * @Last Modified time: 2018-08-02 22:30:59 6 */ 7 #include <stdio.h> 8 #inc

POJ 1113 Wall (凸包 + 思维)

题目:传送门 题意:有一个 n 多边形城堡,先需在城堡外建围墙,使得围墙到城堡的距离不得小于 L,且围墙的周长最小. 思路:答案就是凸包周长 + 半径为 L 的圆的周长.   证明 A.B.C.D四个点,每个点都有 360 度, 然后,角1.2.3.4构成多变形的内角和为 360度,然后每个点,又要减去两个90度,那么剩下的就是圆心角5.6.7.8,它们的和为 4 * (360 - 180) - 360 = 360,刚好是一个圆.推广到任意多边形也是类似的. #include <iostream

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(标准的凸包果题)

题目链接: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. 分析 答案是凸包周长加上一个圆周长,即包围凸包的一个圆角多边形. 但那些圆角加起来为什么恰好是一个圆呢?每个圆角是以凸包对应的顶点为圆心,给定的L为半径,与相邻两条边的切点之间的一段圆弧. 每个圆弧的两条半径夹角与对应的凸包的内角互补.假设凸包有n条边,则所有圆弧角之和为180°*n-180°*(n-2)=360°.(凸边形内角和为(n-2)*180) 故,围墙周长为=n条平