Space Ant
題意:
一張圖上給出n個點的坐標(xi,yi),其中xi,yi均為正整數。記這n個點中,擁有最小y的點為A,你開始從點(0, yA)開始走向點A,然后,你可以隨意選擇徑直走去另外的點,但必須滿足一下3個條件:
1:只能向左轉向。
2:走過的路徑為留下一條紅色的軌跡。
3:不能越過這條紅色的軌跡。
問你最多能到達幾個點,并且按到達的順序輸出各個點的標號。
題解:
本題其實就是用極角排序,每次都有一個你的當前點,然后每次都貪心的走以當前點為中心的極角最小的那個點(如果有多個,就走距離當前點最近的那個點即可.)
這樣,我們能保證能走過的點數是最多的.
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN=60;
const int INF=0x3f3f3f3f3f;
const double EPS=1e-10;
struct Point
{
double x,y;
int id;
Point(double x=0,double y=0):x(x),y(y){}
};
Point p[MAXN],ans[MAXN];
int now;
typedef Point Vector;
Vector operator -(Vector A,Vector B)
{
return Vector(A.x-B.x,A.y-B.y);
}
double cross(Vector A,Vector B)
{
return A.x*B.y-A.y*B.x;
}
double distance(Vector A)
{
return A.x*A.x+A.y*A.y;
}
bool cmp(const Point &a,const Point &b)
{
double res=cross(a-p[now],b-p[now]);//選擇離當前點最外層的點
if(res>0) return true;
else if(abs(res)<EPS&&distance(a-p[now])<distance(b-p[now])) return true;
//如果三點共線,選擇離當前點近的
else return false;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d%lf%lf",&p[i].id,&p[i].x,&p[i].y);
if(p[i].y<p[0].y) swap(p[0],p[i]);
}
now=0;
sort(p+1,p+n,cmp);//以0為基準找到下一個基準點
int idx=0;
ans[idx++]=p[now++];//把0放進去
for(int i=2;i<n;i++)
{
sort(p+i,p+n,cmp);//以now為基準,找到下一個基準點
ans[idx++]=p[now++];//把now放進去
}
ans[idx++]=p[now++];
printf("%d",idx);
for(int i=0;i<idx;i++)
{
printf(" %d",ans[i].id);
}
printf("\n");
}
return 0;
}