極角排序

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;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容