巨人与鬼
随便写了写不知道对不对……
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; }