poj1113 - Wall

133 篇文章 0 订阅

                                    想看更多的解题报告: http://blog.csdn.net/wangjian8006/article/details/7870410
                                     转载请注明出处:
http://blog.csdn.net/wangjian8006

题目大意:给出N个点,问要建一座围墙把这N个点都围起来,并且这做围墙和点的距离不能小于L,问怎么使围墙最短

解题思路:虽然一下就想到了凸包,然后自己写GS算法,结果调了一天,最后发现是定义PI的宏写错了,无限汗颜中,A了之后我很天真的想用两个向量的cos角度去排序,但是怎么调试都是WA,所以还是老实的用叉积排序吧

 

 

/*
200K 32MS
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define INF 1<<30
#define MAXV 1010
#define PI 3.141592653

struct Point{
	double x,y;
}point[MAXV],tmp;

int n,l;

double distance(double x1,double y1,double x2,double y2){
	double dis=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
	return sqrt(dis);
}

int cacl(struct Point a,struct Point b,struct Point h){				//求cos<ha,x>于cos<hb,x>的大小
	double ta=1.0*(a.x-h.x)/distance(a.x,a.y,h.x,h.y);
	double tb=1.0*(b.x-h.x)/distance(b.x,b.y,h.x,h.y);
	if(ta > tb) return 1;
	if(ta==tb) return 0;
	return -1;
}

double chaji(struct Point a1,struct Point b1,struct Point a2,struct Point b2){	//求<a1,b1>向量和<a2,b2>向量的叉积
	double x1=b1.x-a1.x;
	double y1=b1.y-a1.y;
	double x2=b2.x-a2.x;
	double y2=b2.y-a2.y;
	return x1*y2-x2*y1;
}

int cmp(const void *p1,const void *p2){			//排序的比较函数
	struct Point *a=(struct Point *)p1;
	struct Point *b=(struct Point *)p2;
	double flag=chaji(point[0],*a,point[0],*b);
	//int flag=cacl(*a,*b,point[0]);		用cos排序错了,- - !
	if(flag>0)	return -1;						//如果角度是a>b的就直接返回
	else if(!flag && distance((a->x),(a->y),point[0].x,point[0].y)<distance((b->x),(b->y),point[0].x,point[0].y))
		//如果角度a==b的那么取距离小的那一点在前面
		return -1;
	return 1;
}

int findminp(){		//找到最左下点
	int i,v;
	double ymin=INF,xmin=INF;
	for(i=0;i<n;i++)
		if(point[i].y<ymin)
			v=i,ymin=point[i].y;

	for(i=0;i<n;i++)
		if(point[i].y==ymin && point[i].x<xmin)
			v=i,xmin=point[i].x;
	return v;
}

double graham(){
	int d[MAXV],dtop=0;		//模拟栈
	int i;
	double sum;

	d[dtop++]=0;
	d[dtop++]=1;				//前两点入栈
	for(i=2;i<n;i++){
		while(chaji(point[d[dtop-2]],point[d[dtop-1]],point[d[dtop-1]],point[i])<0) dtop--;
		d[dtop++]=i;
	}
	sum=0;
	for(i=1;i<dtop;i++){
		sum+=distance(point[d[i]].x,point[d[i]].y,point[d[i-1]].x,point[d[i-1]].y);
	}
	sum+=distance(point[d[i-1]].x,point[d[i-1]].y,point[d[0]].x,point[d[0]].y);
	return sum;
}

int main(){
	int i,h;
	double ans;
	while(~scanf("%d%d",&n,&l)){
		for(i=0;i<n;i++){
			scanf("%lf%lf",&point[i].x,&point[i].y);
		}
		h=findminp();
		tmp=point[0];
		point[0]=point[h];
		point[h]=tmp;
		qsort(point+1,n-1,sizeof(point[0]),cmp);
		ans=graham()+(2.0*PI*l);
		printf("%.0lf\n",ans);
	}
	return 0;
}


 

 

 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值