POJ 1696 极角排序

题目中指定了ant爬行时的几种规则,从中我们可以知道ant是按照当前所处位置,对其他的plant进行极角排序后,选择角度最小过去,重复,一直到走到最后一个plant。
sort一发就可以了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
const double eps=1e-8;
const int maxn=50+5;
using namespace std;
int N; //点的个数
int sgn(double x){
    if(fabs(x)<eps)
        return 0;
    if(x>0)
        return 1;
    if(x<0)
        return -1;
}
struct point{
    int index; // the index of point
    int x,y;
    point() {}
    point(int _x,int _y){
        x=_x;
        y=_y;
    }
};
typedef point vector;
vector operator + (vector A,vector B){
    return point(A.x+B.x,A.y+B.y);
}
vector operator - (point A,point B){
    return point(A.x-B.x,A.y-B.y);
}
int operator ^ (vector A,vector B){
    return A.x*B.y-A.y*B.x;
}
int operator * (vector A,vector B){
    return A.x*B.x+A.y*B.y;
}
double dis(point a,point b)
{
    return hypot(a.x-b.x,a.y-b.y);
}
point p[maxn];
int q[maxn];
int pos,cnt;
bool cmp(point a,point b) //极角排序函数
{
        int d=(a-p[pos])^(b-p[pos]);            
        if(d==0&&sgn(dis(a,p[pos])-dis(b,p[pos])) < 0 || d>0)
            return true; //共线时取较近的点
        return false;
}
void init(){  //找出起始点
    p[0].y=p[1].y;
    for(int i=1;i<=N;i++)
        if(p[i].y<p[0].y)
            p[0]=point(0,p[i].y);
}
void solve(){
    cnt=0;pos=0;
    for(int i=0;i<N;i++){
        sort(p+pos+1,p+N+1,cmp);
        pos++;
        q[pos]=p[pos].index;
        cnt++;
    }
}
int main(){
    //freopen("input.txt","r",stdin);
    int M;
    cin>>M;
    while(M--){
        memset(p,0,sizeof(p));
        cin>>N;
        for(int i=1;i<=N;i++){
            int index,x,y;
            scanf("%d%d%d",&index,&x,&y);
            p[index]=point(x,y);
            p[index].index=index;
        }
        init();
        solve();
        /*for(int i=1;i<=N;i++)
            printf("(%d,%d)\n",p[i].x,p[i].y);*/
        cout<<cnt;
        for(int i=1;i<=cnt;i++)
            printf(" %d",q[i]);
        cout<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值