题目让找出一条最长的非右拐的路径。
每次找到一个基准点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; }