巨人與鬼(分治&&遞迴)
阿新 • • 發佈:2018-12-12
做這一題學會了 atan2 的用法。
a(x1,y1) b(x2,y2)
向量a=>b = (y2 - y1)/ (x2 - x1)
與x軸正半軸的夾角為 atan2( y2 - y1,x2 - x1)。。。。。
我寫這篇部落格只為記錄我的程式碼:
#include <iostream> #include <cmath> #include <algorithm> using namespace std; const int maxn = 100000; struct point { int x, y, flag, num; } p[maxn], temp; int ans[maxn], n; bool cmp1(point a, point b) { return a.y !=b.y ? a.y < b.y : a.x < b.x; } bool cmp2(point a, point b) { return atan2(a.y - temp.y, a.x -temp.x ) < atan2(b.y - temp.y, b.x - temp.x); } void findx(int left, int right) { if(left > right ) return ; sort(p+left, p+right+1, cmp1); // 找到左下角的點 temp = p[left]; sort(p+left, p+right+1, cmp2); //從 某一邊的弧度開始找。。。 int cnt1 = 0, cnt2 = 0, k = right; //萬一就是這個點呢? while(!(temp.flag != p[k].flag&&cnt1 == cnt2)) { //如果點相同直接停止,如果不同直到找到 相同的 cnt1 和 cnt2 if(temp.flag == p[k].flag) cnt1++; // 相同的加 else cnt2++; //不相同的加 k--; } ans[temp.num] = p[k].num; ans[p[k].num] = temp.num; findx(left + 1, k - 1); findx(k + 1, right); } int main() { cin >> n; for(int i = 1; i <= n; ++i) cin >> p[i].x >> p[i].y >> p[i].flag, p[i].num = i; findx(1,n); for(int i = 1; i <= n; i++) cout << i << " => " << ans[i] <<endl; return 0; } /* 4 1 1 1 2 3 1 3 2 0 7 9 0*/