poj1696 Space Ant

题目让找出一条最长的非右拐的路径。

每次找到一个基准点p0,最开始的时候是最左下角的点,然后我们再从未访问的点中找到相对于p0最小极角的那个点,
比较极角用叉积来计算,所以我们总是每次迭代总是用此次循环中找到的最小极角来代替p0,然后再以
这个新的p0,找到剩下的点中的最小极角,这样我们找到的就是一条最大的不右转的路径了。

代码:

#include <iostream>
#include <stdio.h>
using namespace std;
const int N=50;
const int INF=10000;
struct node{
	int id,x,y;
	node  operator =(const node & t)
	{
		id=t.id;
		x=t.x;
		y=t.y;
		return *this;
	}
};
node s[N+2];;
bool visit[N+2];
int ans[N+2],cas,n;
//右转返回1,否则返回-1
int cross(node p0,node p1,node p2)
{
	int ans=(p2.x-p0.x)*(p1.y-p0.y)-(p2.y-p0.y)*(p1.x-p0.x);
	if(ans>0)
		return 1;
	return -1;
}
int main()
{
	int i,j,minY,minId,minX,top=0;
	node p0,p1,p2;
	bool found=false;
	cin>>cas;
	minId=-1;
	minY=INF;
	minX=INF;
	while(cas--)
	{
		top=0;
		memset(visit,0,sizeof(visit));
		minId=-1;
		minY=INF;
		minX=INF;
		scanf("%d",&n);
		for(i=0;i<n;++i)
		{
			cin>>s[i].id>>s[i].x>>s[i].y;
			//得到最左下角的那个点
			if(s[i].y<minY || ((s[i].y == minY) && (s[i].x<minX)))
			{
				minId=i;
				minY=s[i].y;
				minX=s[i].x;
			}
		}
		visit[minId]=true;
		ans[top++]=minId;
		while(1)
		{
			p0=s[ans[top-1]];
		//	cout<<"p0"<<p0.id<<" "<<p0.x<<" "<<p0.y<<endl;
			found=false;
			//找到最小极角点p1
			for(i=0;i<n;i++)
			{
				if(!visit[i])
				{
					p1=s[i];
					found=true;
					break;
				}
			}
			
			if(!found)
				break;
		//	cout<<"p1"<<p1.id<<" "<<p1.x<<" "<<p1.y<<endl;
			for(j=i+1;j<n;j++)
			{
				if(!visit[j])
				{
					p2=s[j];
					//如果p1需要右转到p2,那么p2的极角小于p1,用p2代替p1
					if(1 == cross(p0,p1,p2))
						p1=p2;
				}
			
			}
			visit[p1.id-1]=true;
			ans[top++]=p1.id-1;
		//	cout<<"p1  next"<<p1.id<<endl;
		}
		printf("%d ",top);
		for(i=0;i<top;i++)
		{
			if(i<top-1)
				printf("%d ",ans[i]+1);
			else
				printf("%d\n",ans[i]+1);
		}
	}
	return 0;
}

 

posted on 2011-11-08 16:38  buptLizer  阅读(554)  评论(0编辑  收藏  举报

导航