# 題目
AP325 Q-5-5. Closest pair
# 解題思路
這題很多假解要小心
假解 1
我在 judge 網站上看到的
上面測資強度不構被他混過去了
#include <bits/stdc++.h> | |
using namespace std; | |
struct POINT{ | |
int x; | |
int y; | |
bool operator < (POINT b){ | |
if (x != b.x) return x < b.x; | |
else return y < b.y; | |
} | |
}; | |
POINT p[100005]; | |
int n; | |
int min_d = 200000001; | |
int minDaC(int l, int r) | |
{ | |
int d, m; | |
if (l >= r) return min_d; | |
m = (l + r) / 2; | |
d = min(minDaC(l, m), minDaC(m+1, r)); | |
for (int i=m+1; p[i].x-p[m].x < d && i<=r; i++){ | |
int dy = abs(p[i].y - p[m].y); | |
if (dy < d) | |
d = min(d, (abs(p[i].x - p[m].x) + dy)); | |
} | |
for (int i=m; p[m+1].x-p[i].x < d && i>=l; i--){ | |
int dy = abs(p[m+1].y - p[i].y); | |
if (dy < d) | |
d = min(d, (abs(p[m+1].x - p[i].x) + dy)); | |
} | |
return d; | |
} | |
int main() | |
{ | |
ios::sync_with_stdio(0), cin.tie(0); | |
cin >> n; | |
for (int i=1; i<=n; i++) | |
cin >> p[i].x >> p[i].y; | |
sort(p+1, p+1+n); | |
// cout << endl; | |
// for (int i=1; i<=n; i++) | |
// cout << p[i].x << ' ' << p[i].y << endl; | |
// cout << endl; | |
cout << minDaC(1, n) << endl; | |
return 0; | |
} |
TLE 解 2
這邊是沒考慮到 y 座標
所以 x 擠在一起會掃到 [mid-d,mid+d] 線內的所有點,退化成 O (n^2 * logn)
極端測資會 TLE
#include <bits/stdc++.h> | |
using namespace std; | |
#define int long long | |
#define Rabbir_Reaper ios::sync_with_stdio(0);cin.tie(0); | |
const int INF = 1LL << 60; | |
vector<pair<int, int>> v; | |
int dist(const pair<int, int> &a, const pair<int, int> &b){ | |
return abs(a.first - b.first) + abs(a.second - b.second); | |
} | |
int solve(int l, int r){ | |
if (r-l == 1) return INF; | |
int mid = (l + r) >> 1; | |
int xmid = v[mid].first; | |
int d = min(solve(l, mid), solve(mid, r)); | |
// 找到 x 值在 [xmid - d, xmid + d] 範圍內的點 | |
int low = lower_bound(v.begin() + l, v.begin() + r, make_pair(xmid - d, LLONG_MAX)) - v.begin(); | |
int high = lower_bound(v.begin() + l, v.begin() + r, make_pair(xmid + d, LLONG_MIN)) - v.begin(); | |
for (int i = low; i < high; i++){ | |
for (int j = i + 1; j < high && (v[j].first - v[i].first) < d; j++){ | |
d = min(d, dist(v[i], v[j])); | |
} | |
} | |
return d; | |
} | |
signed main(){ | |
Rabbir_Reaper | |
int n; | |
cin >> n; | |
v.resize(n); | |
for (int i = 0; i < n; i++){ | |
cin >> v[i].first >> v[i].second; | |
} | |
sort(v.begin(), v.end()); | |
cout << solve(0, n); | |
return 0; | |
} |
# 程式碼
#include <bits/stdc++.h> | |
using namespace std; | |
#define Rabbir_Reaper ios::sync_with_stdio(0),cin.tie(0); | |
#define int long long | |
const int INF = 1LL << 60; | |
vector<pair<int, int>> v; | |
int dist(const pair<int, int> &a, const pair<int, int> &b){ | |
return abs(a.first - b.first) + abs(a.second - b.second); | |
} | |
int solve(int l, int r){ | |
if(r-l == 1) return INF; | |
int mid = (l + r) >> 1; | |
int xmid = v[mid].first; | |
int d = min(solve(l, mid), solve(mid, r)); | |
vector<pair<int,int>> strip; | |
for (int i = l; i < r; i++){ | |
if (abs(v[i].first - xmid) < d) | |
strip.push_back(v[i]); | |
} | |
sort(strip.begin(), strip.end(), [](const pair<int, int> &a, const pair<int, int> &b){ | |
return a.second < b.second; | |
}); | |
// 掃描最近的 7 個點 | |
for(int i = 0; i < strip.size(); i++){ | |
for(int j = i + 1; j < strip.size() && (strip[j].second - strip[i].second) < d; j++){ | |
d = min(d, dist(strip[i], strip[j])); | |
} | |
} | |
return d; | |
} | |
signed main(){ | |
Rabbir_Reaper | |
int n; | |
cin >> n; | |
v.resize(n); | |
for (int i = 0; i < n; i++){ | |
cin >> v[i].first >> v[i].second; | |
} | |
sort(v.begin(), v.end()); | |
cout << solve(0, n) << "\n"; | |
return 0; | |
} |