hdu 1348 Wall (凸包模板)

题目链接:hdu 1348

Wall

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)

Problem 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.

This problem contains multiple test cases!

The first line of a multiple input is an integer N, then a blank line followed by N input blocks. Each input block is in the format indicated in the problem description. There is a blank line between input blocks.

The output format consists of N output blocks. There is a blank line between output blocks.

Sample Input 
1

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

Sample Output 
1628

题目稍微有点长。

题意是说一个国王给你一些点,这些点组成一个城堡,国王要求在这个多边形形状的城堡周围建起周长最小的城墙,并且城墙与城堡的距离处处不得小于L。

注意:求围墙的周长非常的简单,计算出凸包的周长之后,然后使用加上一个圆的周长就可以了。

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

struct node{
    int x;
    int y;
};
int xx,yy;//记录基点的位置 
node vex[1000];//一个数组存放点 
node stackk[1000];//保存凸包中的所有顶点,是一个模拟的栈 
int cross(node a,node b,node c)
{
    return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
double dis(node a,node b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)*1.0 + (a.y-b.y)*(a.y-b.y)*1.0);
}
bool cmp1(node a,node b)
{
    //首先找基点,纵坐标最小的一定在凸包上,如果纵坐标相等那么就选横坐标小的
    if(a.y!=b.y) return a.y<b.y;
    else return a.x<b.x;
}
//atan2(y,x)所表达的意思是坐标原点为起点,指向(x,y)的射线在坐标平面上与x轴正方向之间的角的角度。
bool cmp2(node a,node b)
{
    if(atan2(a.y-yy,a.x-xx)!=atan2(b.y-yy,b.x-xx))
        return atan2(a.y-yy,a.x-xx) < atan2(b.y-yy,b.x-xx);
    else return a.x<b.x;    
} 
int main(void)
{
    int t,L;
    while(scanf("%d%d",&t,&L)!=EOF&&t&&L)
    {
        int i;
        for(i=0;i<t;i++) scanf("%d%d",&vex[i].x,&vex[i].y);
        
        if(t==1) 
        {
            printf("%.2lf\n",0.00);
        }
        else if(t==2)
        {
            printf("%.2lf\n",dis(vex[0],vex[1]));
        }
        else 
        {
            memset(stackk,0,sizeof(stackk));
            //首先找基点,纵坐标最小的一定在凸包上,如果纵坐标相等那么就选横坐标小的
            sort(vex,vex+t,cmp1);
            //基点入栈 
            stackk[0]=vex[0]; 
            xx=stackk[0].x;
            yy=stackk[0].y;
            
            //极角排序
            sort(vex+1,vex+t,cmp2);
            //将凸包中第二个点存入凸包的结构体中
            stackk[1]=vex[1];
            int top = 1;
            for(i=2;i<t;i++)
            {
                //对使用极角排序的i>=1可以不使用,但是加上总是好的 
                while(i>=1 && cross(stackk[top-1],stackk[top],vex[i])<0)
                    top--;
                stackk[++top]=vex[i];
                //控制<0 或者<=0可以控制重复点,共线点,具体看题目情况而定                        
            }
            //计算凸包的周长,注意第一个点和最后一个点 
            double s = 0;
            for(i=1;i<=top;i++) s+=dis(stackk[i-1],stackk[i]);
            s+=dis(stackk[0],stackk[top]);
            //输出凸包上面的点
            for(i=0;i<=top;i++) 
            {
                printf("(%d,%d)\n",stackk[i].x,stackk[i].y);
            }
            //输出长度 
            printf("周长为:%.2lf\n",s); 
            printf("围墙的长度:%.2lf\n",s+2*PI*L);
        }
    } 
    return 0;
} 

这样就学会了解决凸包的问题。

猜你喜欢

转载自www.cnblogs.com/zuimeiyujianni/p/9020686.html
今日推荐