題目: UVa - 11378 - Bey Battle

題目說明

給你點的位置,求出以各個點為中心的正方形,邊長最多可達多少?每個正方形邊長須一樣,可剛好接觸到。

UVa 11378 - Bey Battle | NaiveRed’s Blog

解題思路

Closet Pair Problem,可用 Divide and Conquer。

參考解法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <bits/stdc++.h>

using namespace std;

#define FOR(i, a, b) for (int i = a; i < b; ++i)
#define CLR(c) memset(c, 0, sizeof(c))

static auto __ = []
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
return 0;
}();

// reference: https://ppt.cc/fZxscx

const int INF = (int)1e9;
const int MXN = 100000;

struct Point
{
int x;
int y;
};

Point P[MXN];
Point tmp[MXN];

int N;

int dist(const Point& l, const Point& r)
{
return max(abs(l.x - r.x), abs(l.y - r.y));
}

bool cmp1(const Point& l, const Point& r)
{
return l.x < r.x;
}

bool cmp2(const Point& l, const Point& r)
{
return l.y < r.y;
}

void read()
{
FOR(i, 0, N) cin >> P[i].x >> P[i].y;
}

int DnC(int L, int R)
{
if (L >= R) return INF;

auto M = (L + R) / 2;
auto d = min(DnC(L, M), DnC(M + 1, R));

int idx = 0;
for (int i = M; i >= L && P[M].x - P[i].x < d; --i) tmp[idx++] = P[i];
for (int i = M + 1; i <= R && P[i].x - P[M].x < d; ++i) tmp[idx++] = P[i];

sort(tmp, tmp + idx, cmp2);

FOR(i, 0, idx) FOR(j, 1, 4 && i + j < idx) d = min(dist(tmp[i], tmp[i + j]), d);

return d;
}

void solve()
{
sort(P, P + N, cmp1);
auto ret = DnC(0, N - 1);
cout << ret << '\n';
}

int main()
{
while (cin >> N && N)
{
read();
solve();
}
}

參考資料

UVa 11378 - Bey Battle | NaiveRed’s Blog