您的位置:首页 > 其它

poj1113 凸包

2013-03-10 13:19 274 查看
题目链接:http://poj.org/problem?id=1113

首先注意的是在c或c++中用强制类型转换将浮点型数据转换为int型的时候是只取整数部分的,要进行四舍五入需要在浮点数据上加0.5来进行,这道题就是让我在这里WA了几次,刚开始也有想到,但是没有改,然后在网上搜测试数据,然后就发现还是这样的错误,也罢,吃一堑长一智!

题目大意是给你一个城堡外围转折点的坐标,让你找到一个长度最短的城墙将城堡围起来,而且围墙离城堡的距离最少有l距离的!

大致思路:采用凸包,找到城堡最外围的点,然后围墙的长度就为所有外围的点的距离和加上接点的距离,因为有最小的距离了,就需要生成点a的两条线求其夹角,然后根据圆的周长公式求得,下面是代码:

 

#include<iostream>
#include<cstdio>
#include<cmath>
#include<stack>
using namespace std;
#define pi 3.14159265358
typedef struct point
{
int x,y;
}rr;
point a[1005],*p;
int b[1005];
int n,l;
int Sort(point p1,point p2,point p3,point p4)
{
int t=(p2.x-p1.x)*(p4.y-p3.y)-(p4.x-p3.x)*(p2.y-p1.y);
return t;
}
int distance(point p1,point p2,point p3,point p4)
{
return (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)>(p3.x-p4.x)*(p3.x-p4.x)+(p3.y-p4.y)*(p3.y-p4.y)?1:-1;
}
int cmp(const void *a,const void *b)
{
point *c=(point *)a;
point *d=(point *)b;
int temp=Sort(*p,*c,*p,*d);
if(temp<0)
return 1;
else if(temp==0)
return distance(*p,*c,*p,*d);
else
return -1;
}
void foud()//将点集合的所有的外边的点找出来
{
int i,pc=2;
b[1]=0;
b[2]=1;
b[0]=2;//记录的是总的个数的
for(i=2; ;)
{
i=i%n;///需要将0的也进行一下再结合
if(i==1)
break;
if(b[0]==1)
{
b[++pc]=i++;
b[0]++;
continue;
}
if(Sort(a[b[pc-1]],a[b[pc]],a[b[pc]],a[i])<=0)//删除pc所在的那个店的
{
pc--;
b[0]--;
}
else
{
b[++pc]=i++;//最后的栈的后面多了一个0是为了下面进行的操作的
b[0]++;
}
}
n=pc-1;//1到pc的结果的
b[0]=b[pc-1];//为了循环的
//	for(i=0; i<=n+1; i++)
//		printf("%d\n",b[i]);
}
double dis(point p1,point p2)
{
double s=(double)((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
s=sqrt(s);
return s;
}
double degree(point p1,point p2,point p3,point p4)
{
double s=(double)((p2.x-p1.x)*(p4.x-p3.x)+(p2.y-p1.y)*(p4.y-p3.y));
double t=dis(p1,p2)*dis(p3,p4);
return acos(s/t);//算出来的是角度
}
void len()
{
double Max=0;
int i;
for(i=1; i<=n; i++)
Max+=sqrt((double)((a[b[i]].x-a[b[i+1]].x)*(a[b[i]].x-a[b[i+1]].x)+(a[b[i]].y-a[b[i+1]].y)*(a[b[i]].y-a[b[i+1]].y)));//求一部分的边长的
for(i=1; i<=n; i++)
{
double m=degree(a[b[i]],a[b[i-1]],a[b[i]],a[b[i+1]]);
m=pi-m;//对角的
Max+=l*m;
}
printf("%d\n",(int)(Max+0.5));
}
int main()
{
int i,j,x,y;
while(scanf("%d%d",&n,&l)!=EOF)
{
x=INT_MAX;
y=INT_MAX;
for(i=0; i<n; i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
if(a[i].y<y)
{
y=a[i].y;j=i;x=a[i].x;
}
else if(a[i].y==y && a[i].x<x)
{
y=a[i].y;j=i;x=a[i].x;
}
}
a[j].x=a[0].x;a[j].y=a[0].y;
a[0].x=x;a[0].y=y;
p=&a[0];
qsort(&a[1],n-1,sizeof(point),cmp);
//		for(i=0; i<n; i++)
//			printf("%d  %d  %d\n",i,a[i].x,a[i].y);
foud();
len();//计算需要的篱笆的长度
}
return 0;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: