給定一個 $N \times M$ 的地圖,1 代表土地,0 代表海洋。我們需要找出地圖中所有的「連通土地」(上下左右相連),並針對每一塊領土輸出以下資訊:
最左上角的座標 (最小的 $x$ 與 $y$)。
最右下角的座標 (最大的 $x$ 與 $y$)。
面積 (該塊區域中 1 的總數)。
我們可以使用 DFS 或 BFS 遍歷整張地圖:
遍歷地圖:當遇到一個 1 且該點尚未被訪問過,代表發現了一塊新領土。
開始搜索:從該點出發,搜索所有相連的 1。
更新屬性:在搜索過程中:
紀錄遇到的最小 $x$、最小 $y$、最大 $x$、最大 $y$。
每找到一個 1,面積計數器就 $+1$。
標記已訪問:將走過的 1 改成 0(或使用 vis 陣列),避免重複計算。
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int map[505][505];
int R, C;
int minX, minY, maxX, maxY, area;
// 方向陣列:上下左右
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};
void dfs(int x, int y) {
// 標記為已訪問 (淹沒它)
map[x][y] = 0;
area++;
// 更新邊界
minX = min(minX, x);
minY = min(minY, y);
maxX = max(maxX, x);
maxY = max(maxY, y);
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
// 檢查邊界與是否為土地
if (nx >= 0 && nx < R && ny >= 0 && ny < C && map[nx][ny] == 1) {
dfs(nx, ny);
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
// 題目通常先給 寬(C) 再給 高(R)
while (cin >> C >> R) {
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
cin >> map[i][j];
}
}
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
if (map[i][j] == 1) {
// 初始化領土資訊
minX = maxX = i;
minY = maxY = j;
area = 0;
dfs(i, j);
// 輸出格式:左上 y x, 右下 y x, 面積
// 注意:題目座標可能是 (橫向, 縱向),輸出請依題目要求調整
cout << minY << " " << minX << " " << maxY << " " << maxX << " " << area << "\n";
}
}
}
}
return 0;
}
座標順序:題目通常以 $x$ 代表水平方向(行),$y$ 代表垂直方向(列)。在輸出時請務必看清楚是先輸出 $x$ 還是 $y$。
遞迴深度:地圖如果很大(例如 $500 \times 500$ 且全部都是 1),DFS 可能會導致 Stack Overflow。在這種情況下,建議改用 BFS (使用 std::queue) 或是增加系統堆疊大小。
讀取方向:注意 cin >> C >> R 還是 cin >> R >> C。