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;

}

 

你可能感兴趣的:(ant)