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;
}
浙公网安备 33010602011771号