UVa 10486 - Mountain Village

contents

  1. 1. Problem
  2. 2. Input
  3. 3. Output
  4. 4. Solution

Problem

給定一個 n x m 的網格,現在要紮營於格子上,但是每一格的高度不同,希望使用 k 個格子,他們可以藉由上下左右四格相連,找一種方案,使得最低、最高紮營高度差最小。

Input

1
2
3
4
5
6
7
8
9
10
11
12
13
5 10
0 0 3 46 0 46 0 0 12 12
0 0 13 50 49 46 11 10 10 11
0 51 51 49 99 99 89 0 0 10
0 0 48 82 70 99 0 52 13 14
51 50 50 51 70 35 70 10 14 11
6
1
5
10
12
47
50

Output

1
2
3
4
5
6
0
0
3
4
89
99

Solution

由於高度介於 0 到 100 之間,考慮窮舉最低紮營處的高度 l。採用掃描線的方式,依序加入高度較低的地點,直到其中一個連通子圖的節點總數大於等於 k。

為了加速,使用并查集來完成合併連通子圖。

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
85
86
87
88
89
90
91
92
#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
const int MAXN = 64;
int A[MAXN][MAXN];
vector< pair<int, int> > g[128];
int parent[MAXN*MAXN], weight[MAXN*MAXN];
int findp(int x) {
return parent[x] == x ? x : parent[x] = findp(parent[x]);
}
int joint(int x, int y) {
x = findp(x), y = findp(y);
if (x == y) return 0;
if (weight[x] > weight[y])
weight[x] += weight[y], parent[y] = x;
else
weight[y] += weight[x], parent[x] = y;
return 1;
}
void init(int n) {
for (int i = 0; i <= n; i++)
parent[i] = i, weight[i] = 1;
}
const int dx[] = {0, 0, 1, -1};
const int dy[] = {1, -1, 0, 0};
int query(int n, int m, int need) {
int x, y, tx, ty;
int ret = 0x3f3f3f3f;
for (int i = 0; i < 100; i++) { // lower
init(n * m);
int ok = 0;
for (int j = i; j < 100 && !ok; j++) { // upper
if (j - i >= ret)
break;
for (int k = 0; k < g[j].size() && !ok; k++) {
x = g[j][k].first, y = g[j][k].second;
for (int d = 0; d < 4; d++) {
tx = x + dx[d], ty = y + dy[d];
if (tx < 0 || ty < 0 || tx >= n || ty >= m)
continue;
if (A[tx][ty] <= j && A[tx][ty] >= i) {
joint(x * m + y, tx * m + ty);
if (weight[findp(x * m + y)] >= need)
ok = 1, ret = min(ret, j - i);
}
}
}
}
}
return ret;
}
int main() {
int n, m, q, x;
while (scanf("%d %d", &n, &m) == 2) {
for (int i = 0; i < 100; i++)
g[i].clear();
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
scanf("%d", &A[i][j]);
g[A[i][j]].push_back(make_pair(i, j));
}
}
scanf("%d", &q);
for (int i = 0; i < q; i++) {
scanf("%d", &x);
printf("%d\n", query(n, m, x));
}
}
return 0;
}
/*
5 10
0 0 3 46 0 46 0 0 12 12
0 0 13 50 49 46 11 10 10 11
0 51 51 49 99 99 89 0 0 10
0 0 48 82 70 99 0 52 13 14
51 50 50 51 70 35 70 10 14 11
6
1
5
10
12
47
50
*/