HDU Wall(凸包)


Wall

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2371    Accepted Submission(s): 652


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
 

Source
 

Recommend
JGShining
 


这个题目赤裸裸的凸包问题了,但是过的比例和人数不多有点不解,估计是pe造成的,在杭电上总是喜欢在格式上下功夫,不解,POJ上也有这个题目,不过在格式上要求
简单多了!

graham扫描法来寻找凸包,看了别人的代码好多都应以一些栈什么的辅助数组
但是我没有,全部都是在一个数组里面完成,其实是完全可以的。因为我们在选择或者淘汰的时候从前面向后面,那么前面搞定后的数组就可以利用了嘛
因为留下来的总是比原来要少的!
下面具体介绍一下程序步骤:
第一步:
寻找最下面的点,也就是y值最小的点,这个点毫无疑问是凸包上面的点,也可以知道这个点是我们第一个找到在凸包上的点
第二步:
按照极角排序,就是按照,因为这里用的是qsort那么在排序的时候每次涉及到两个点,那么这两个点谁在前面,谁在后面就要
有一个比较,这个比较函数就是
int cmp(const void *a,const void *b)
{
return across(po[0],*(point*)a,*(point*)b) > 1e-8 ? -1 : 1;
}
根据两点和最低点组成三角形的面积正负来作为判断条件,达到按照极角排序的效果
第三步:
去除一些一定不会在凸包上的点,也就是最低点和另外两个点共线的情况,那么只要留下离最低点远的那个点
第四步:
前面的都是辅助,这里是核心,从剩下的点中选择在凸包上的点,首先明确一点,假设只有三个点,那么经过上面几步之后剩下来的三个点一定可以组成凸包
那么首先前三个放在凸包里面,然后开始选择,选择的时候以这样方式选择
for(i=3;i<num;i++)
{
while(across(po[k-1],po[k],po[i]) < -eps)
{k--;}
po[++k]=po[i];//就这个循环结束,不需要了!
}
最后选择的两个在凸包上的点,和当前正要选择的点会组成一个三角形,如果面积为正,那么可以选择,如果面积为负,那么说明先前选择的那个点有问题
造成了不是凸包,应该去除,所以k--,接下来循环判断,这样就保证了已经选择的点的一个凸性

最后强调一点小技巧,在graham扫描的时候把第一个点加到最后,这样能省很多事情,减少个边界情况的考虑!



#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <cmath>
using namespace std;
#define eps 1e-6
#define PI 3.14159265
struct point
{
double x;
double y;
}po[1500],temp;
int n,l,pos;
bool zero(double a)
{
return fabs(a) < eps;
}
double dis(point &a,point &b)//返回两点之间距离的平方
{
return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y);
}
double across(point &a,point &b,point &c)//求a b and a c 的X积
{
return (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x);
}
int cmp(const void *a,const void *b)
{
return across(po[0],*(point*)a,*(point*)b) > 1e-8 ? -1 : 1;
}
int select()
{
int i,j,k=1;
for(i=2;i<n;i++)
{
if(zero(across(po[0],po[k],po[i])))
{
if(dis(po[0],po[k]) < dis(po[0],po[i]))
po[k]=po[i];
}
else
po[++k]=po[i];
}
return k+1;
}
int graham(int num)
{
double ans=PI*l*2;
int i,j,k=2;
po[num]=po[0];//fangbian 
num++;
for(i=3;i<num;i++)
{
while(across(po[k-1],po[k],po[i]) < -eps)
{k--;}
po[++k]=po[i];//就这个循环结束,不需要了!
}
for(i=1;i<=k;i++)
{
ans+=sqrt(dis(po[i-1],po[i]));
}
if(ans-int(ans) > 0.5)
printf("%d\n",int(ans)+1);
else
printf("%d\n",int(ans));

return 0;
}
int main()
{
int i,j,k;
point my_temp;
int t;
scanf("%d",&t);
while(t--)
{scanf("%d%d",&n,&l);
scanf("%lf%lf",&po[0].x,&po[0].y);
temp=po[0];
pos=0;
for(i=1;i<n;i++)
{
scanf("%lf%lf",&po[i].x,&po[i].y);
if(po[i].y < temp.y)
temp=po[i],pos=i;
}
my_temp=po[0];
po[0]=po[pos];
po[pos]=my_temp;
qsort(po+1,n-1,sizeof(po[0]),cmp);
graham(select());
if(t>0)
printf("\n");
}
return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值