您的位置:首页 > 其它

HDU 4946 Area of Mushroom (凸包)

2014-08-15 20:09 411 查看
题目链接:HDU 4946 Area of Mushroom

题意:有N个学生,给出他们的位置和速度。若他们能管辖的范围是无穷大的为1,反之,为0.

官方的题解:



注意:

1.最大速度为0。所有的点范围都是0.

2.经过凸包算法后,还要判断那些 能凸包的点 和 在凸包上的点 是否共线。

3.去除凸包上重复的点。

AC代码:

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<set>
#include<map>
#define M 1100+10
using namespace std;

struct node
{
	int x,y,k;
	int ans,indx;
	int ok;
};
struct node ansp[M],p[M],v[M];

node operator- (node a,node b)
{
	node c;
	c.x=a.x-b.x,c.y=a.y-b.y;
	return c;
}
double cross(node a,node b)
{
	return a.x*b.y-b.x*a.y;
}
bool cmp(node a,node b)
{
	if(b.k!=a.k)
		return a.k>b.k;
	if(b.x!=a.x)
		return a.x<b.x;
	if(b.y!=a.y)
		return a.y<b.y;
	return false;
}
bool cmp1(node a,node b)
{
	return a.indx<b.indx;
}
int graham(int n)
{
//	sort(p,p+n,cmp);
	int i,t,s=0,cnt=0;
	for(i=0;i<n;i++)
	{
		while(s>=2 && cross(ansp[s-1]-ansp[s-2],p[i]-ansp[s-2])<=0)
			s--;
		ansp[s++]=p[i];//凸包上的点
	}
	t=s;
	for(i=n-2;i>=0;i--)
	{
		while(s>t && cross(ansp[s-1]-ansp[s-2],p[i]-ansp[s-2])<=0)
			s--;
		ansp[s++]=p[i];
	}
	if(n>1) s--;
	return s;
}

void gongxian(int n,int m)
{
	int i,j;
	for(i=0;i<n;i++)//能凸包的点
	{
		for(j=0;j<m;j++)//凸包上的点
		{
			if(cross(ansp[j]-ansp[(j+1)%m],ansp[j]-v[i])==0)//判断是否共线
			{
				if(v[i].ok)//是否重点
					v[i].ans=1;
				break;
			}
		}
	}
}
void init()
{
	memset(p,0,sizeof p);
	memset(v,0,sizeof v);
	memset(ansp,0,sizeof ansp);
}
int main()
{
	int cas=1;
	int n,i,l,k,j;
	while(scanf("%d",&n)!=EOF,n)
	{
		init();
		for(i=0;i<n;i++)
		{
			scanf("%d %d %d",&v[i].x,&v[i].y,&v[i].k);
			v[i].indx=i;
			v[i].ok=1;
			v[i].ans=0;
		}
		sort(v,v+n,cmp);
		if(v[0].k==0)//最大速度为0
		{
			printf("Case #%d: ",cas++);
			for(i=0;i<n;i++)
				printf("0");
			printf("\n");
			continue;
		}
		for(i=1;i<n;i++)
		{
			if(v[i].k!=v[i-1].k)//找 能凸包的点
				break;
			if(v[i].x==v[i-1].x && v[i].y==v[i-1].y)//速度相同 且是重点
				v[i-1].ok=v[i].ok=0;
		}
		int cnt=i;
		for(i=0;i<cnt;i++)//前cnt个点是能进行凸包的
			p[i]=v[i];
		k=graham(cnt);
		gongxian(cnt,k);
		sort(v,v+n,cmp1);
		printf("Case #%d: ",cas++);
		for(i=0;i<n-1;i++)
			printf("%d",v[i].ans);
		printf("%d\n",v[i].ans);
	}
	return 0;
}
/*

3
1 1 1
1 1 1
1 1 1

4
1 1 2
1 1 3
0 0 3
2 2 1

5
0 0 3
2 0 3
2 2 3
0 2 3
0 1 3

4
1 1 0
1 1 0
0 0 0
2 2 0

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