巨人与鬼

随便写了写不知道对不对……

2333333

主要:考虑y坐标最小的点,y轴坐标相同则考虑最左边的点。则其他所有点的极角都在(0,Pi]之间,对极角从小到大排序。不妨设那个点为巨人

则如果第一个点是鬼则完成配对,如果并不是鬼则,按照极角顺序从小到大检查一直到巨人数目和鬼的数目一致,然后进行下一轮递归……

////啊啊啊啊,极角排序……!

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <stack>
#include <cctype>
#include <string>
#include <malloc.h>
#include <queue>
#include <map>

using namespace std;

const int INF = 0xffffff;
const double esp = 10e-8;
const double Pi = 4 * atan(1.0);
const int Maxn = 2000+10;
const long long mod =  2147483647;
const int dr[] = {1,0,-1,0,-1,1,-1,1};
const int dc[] = {0,1,0,-1,1,-1,-1,1};
typedef long long LL;

LL gac(LL a,LL b){
    return b?gac(b,a%b):a;
}

struct guest{
    double x,y,angle;
    int v;
    int num1;
    int num2;
    bool operator < (const guest a)const{
        if(abs(y-a.y) < esp)
            return x < a.x;
        return y < a.y;
    }
};

bool cmp(const guest a,const guest b){
    return a.angle < b.angle;
}

double get_angle(guest a,guest b){
    if(abs(a.x - b.x) < esp)
        return atan(0xfffffff);
    double tt = atan((a.y-b.y)/(a.x-b.x));
    if(tt < 0)
        tt += Pi;
    return tt;
}

guest arr[1000];

void dis(int s,int e){
    if(e-s == 1){
        arr[s].num2 = arr[e].num1;
        arr[e].num2 = arr[s].num1;
        return;
    }
    sort(arr+s,arr+e+1);
    int sum = arr[s].v;
    for(int i = s+1;i <= e;i++){
        arr[i].angle = get_angle(arr[s],arr[i]);
    }
    sort(arr+s+1,arr+e+1,cmp);
    int t = s;
    while(sum){
        sum += arr[++t].v;
    }
    dis(s,t);
    dis(t+1,e);
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("inpt.txt","r",stdin);
#endif
    int n;
    while(~scanf("%d",&n)){
        for(int i = 0;i < n;i++){
            scanf("%d%lf%lf",&arr[i].num1,&arr[i].x,&arr[i].y);
            arr[i].v = 1;
            arr[i].num2 = 0;
        }
        for(int i = n;i < 2*n;i++){
            scanf("%d%lf%lf",&arr[i].num1,&arr[i].x,&arr[i].y);
            arr[i].v = -1;
            arr[i].num2 = 0;
        }
        dis(0,2*n-1);
        for(int i = 0;i < 2*n;i++){
            if(arr[i].v > 0){
                cout << arr[i].num1 << ' ' << arr[i].num2 << endl;
            }
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/hanbinggan/p/4299599.html