巨人与鬼
问题描述:
代码实现:
1 #include <iostream> 2 #include <cmath> //包含atan2(double,double)函数,求正切值 3 #include <algorithm> 4 using namespace std; 5 const int maxn = 100000; 6 struct point { 7 int x, y, flag, num; //flag 取0,1值,表示鬼和巨人 8 } p[maxn], temp; 9 int ans[maxn], n; 10 11 bool cmp1(point a, point b) 12 { 13 return a.y !=b.y ? a.y < b.y : a.x < b.x; 14 } 15 16 bool cmp2(point a, point b) 17 { 18 return atan2(a.y - temp.y, a.x -temp.x ) < atan2(b.y - temp.y, b.x - temp.x); 19 } 20 21 void findx(int left, int right) 22 { 23 if(left > right ) return ; 24 sort(p+left, p+right+1, cmp1); // 找到左下角的点,sort右不包含 25 temp = p[left]; 26 sort(p+left, p+right+1, cmp2); //从 某一边的弧度开始找。。。弧度排序后,temp=p[left] 27 int cnt1 = 0, cnt2 = 0, k = right; 28 while(!(temp.flag != p[k].flag&&cnt1 == cnt2)) //当p[k]和tempflag不同,且cnt1==cnt2时,temp(也就是按角度排序后的p[left])正好和p[k]组一队, 29 //连线一边已经有cnt1对可以继续递归划分,另一边无疑也是整数对可以继续划分 30 31 { 32 if(temp.flag == p[k].flag) cnt1++; // 相同的加 巨人 33 else cnt2++; //不相同的加 鬼 34 k--; 35 } 36 ans[temp.num] = p[k].num; 37 ans[p[k].num] = temp.num; 38 findx(left + 1, k - 1); 39 findx(k + 1, right); 40 } 41 42 int main() 43 { 44 cin >> n; 45 for(int i = 1; i <= n; ++i) cin >> p[i].x >> p[i].y >> p[i].flag, p[i].num = i; 46 findx(1,n); 47 for(i = 1; i <= n; i++) cout << i << " => " << ans[i] <<endl; 48 return 0; 49 }
//原文参考:https://blog.csdn.net/FireflyNo1/article/details/82869095
运行结果: