分治_平面最近點對_POJ3714_Raid
阿新 • • 發佈:2018-12-17
思路分析:
AC程式碼如下, 就下面程式碼而言, 比較容易理解, 不予分析, 但是應該強調, 下面的程式碼不能算作典型的分治法求解平面最近點對的演算法, 為什麼這麼說 ? 因為經典的分治法求解平面最近點對的演算法(可參考演算法導論第33章第4節)的最壞情況時間複雜度為O(nlg(n)), 然而就下面給出的程式碼而言其最壞情況時間複雜度的階嚴格高於nlg(n)
//POJ3714_Raid #include <cstdio> #include <algorithm> #include <cmath> using namespace std; typedef long double LD; const int MAX = 2e5 + 5; const LD NIL = 1e15; pair<pair<int, int>, bool> p[MAX], ptmp[MAX];//first:座標, second:true表示電站,false表示代理人 bool cmpx(const pair<pair<int, int>, bool> a, pair<pair<int, int>, bool> b){ return a.first.first < b.first.first; } //返回p[l...r]中電站和代理人的最小距離, LD solve(int l, int r){ if(l == r) return NIL; int mid = (l + r) >> 1, midx = p[mid].first.first; LD ansl = solve(l, mid), ansr = solve(mid + 1, r), ans; ans = min(ansl, ansr); int ptmplen = 0; for(int i = l; i <= r; ++i) if(abs(p[i].first.first - midx) <= ans) ptmp[++ptmplen] = p[i]; for(int i = 1; i <= ptmplen; ++i) for(int j = i + 1; j <= ptmplen ; ++j) if(ptmp[i].second != ptmp[j].second) ans = min(ans, sqrt((LD)(ptmp[i].first.first - ptmp[j].first.first) * (ptmp[i].first.first - ptmp[j].first.first) + (LD)(ptmp[i].first.second - ptmp[j].first.second) * (ptmp[i].first.second - ptmp[j].first.second))); return ans; } int main(){ int T; scanf("%d", &T); while(T--){ int N; scanf("%d", &N); for(int i = 1, x, y; i <= N; ++i) scanf("%d %d", &x, &y), p[i] = make_pair(make_pair(x, y), true); for(int i = N + 1, x, y; i <= N << 1; ++i) scanf("%d %d", &x, &y), p[i] = make_pair(make_pair(x, y), false); sort(p + 1, p + 2 * N + 1, cmpx);//先按照橫座標非遞減排序 printf("%.3Lf\n", solve(1, N << 1)); } }