紅與黑[DFS]
阿新 • • 發佈:2021-01-17
紅與黑[DFS]
文章目錄
題目描述
有一間長方形的房子,地上鋪了紅色、黑色兩種顏色的正方形瓷磚。
你站在其中一塊黑色的瓷磚上,只能向相鄰(上下左右四個方向)的黑色瓷磚移動。
請寫一個程式,計算你總共能夠到達多少塊黑色的瓷磚。
輸入格式
輸入包括多個數據集合。
每個資料集合的第一行是兩個整數 WW 和 HH,分別表示 xx 方向和 yy 方向瓷磚的數量。
在接下來的 HH 行中,每行包括 WW 個字元。每個字元表示一塊瓷磚的顏色,規則如下
1)‘.’:黑色的瓷磚;
2)‘#’:紅色的瓷磚;
當在一行中讀入的是兩個零時,表示輸入結束。
輸出格式
對每個資料集合,分別輸出一行,顯示你從初始位置出發能到達的瓷磚數(記數時包括初始位置的瓷磚)。
資料範圍
1≤W,H≤201≤W,H≤20
6 9
....#.
.....#
......
......
......
......
......
#@...#
.#..#.
0 0
輸出樣例:
45
思路分析
-
應題目要求,我們只能找到,‘@’與其他黑磚相連的區域,並記錄黑磚的個數就是答案。
-
首先分析,每次座標變換的偏移量, 以下圖為例分析。
-
由題可知,每次移動只能向上下左右移動一個瓷磚,所以和以得到,x軸和y軸的偏移量,**注意:**這裡說的 x軸 指的是——以左上交為原點,向下為 x正半軸,向右為 y軸負半軸。
-
得到 x和y軸的偏移量,可以存在陣列中(方便計算相鄰的點)。
-
演算法
- 本題用到了深度優先搜尋,簡稱DFS。
- 深度優先搜尋就是,先選中一條路徑一直走,走到底,然後沒路了,返回上一個交叉口(選擇的地方),走其他的路徑,也就是嘗試求出每種結果找出正確答案。
- 本題,就是一個簡單的dfs求連通區域。首先,由題可知每個瓷磚只能計算一次,所以需要用一個 標記 陣列, 來記錄當前瓷磚是否已經計算過了。最後得到的就是答案。
- 本題用到了深度優先搜尋,簡稱DFS。
AC程式碼
java程式碼
import java.util.Scanner;
public class Main {
public static int[] dx = {-1, 1, 0, 0}; // x軸偏移量
public static int[] dy = {0, 0, -1, 1}; // y軸偏移量
public static int ans = 0;
public static int n = 0;
public static int m = 0;
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
while (true) {
m = cin.nextInt();
n = cin.nextInt();
if (n == 0 && m == 0) break;
ans = 0;
cin.nextLine();
boolean[][] v = new boolean[n][m]; // 定義標記陣列
StringBuilder[] mp = new StringBuilder[n]; // 儲存輸入的地圖
int x = 0, y = 0, f = -1;
for (int i = 0; i < n; ++ i) {
mp[i] = new StringBuilder(cin.nextLine());
f = mp[i].indexOf("@");
if (f != -1) { // 找到開始位置
x = i;
y = f;
}
}
dfs(x, y, v, mp); // 進行深度優先搜尋
System.out.println(ans);
}
}
public static void dfs(int x, int y, boolean[][] v, StringBuilder[] mp) {
v[x][y] = true; // 標記當前,x,y座標的函式已經計算過了
ans ++;// 加入答案
for (int i = 0; i < 4; ++ i) { // 判斷當前黑瓷磚周圍的其他磚
int nx = x + dx[i];
int ny = y + dy[i];
// 判斷 座標是否超過陣列大小,判斷當前瓷磚是否記錄過,判斷當前周邊瓷磚是否為黑瓷磚
if (nx < 0 || nx >= n || ny < 0 || ny >= m || v[nx][ny] == true || mp[nx].charAt(ny) == '#') continue;
dfs(nx, ny, v, mp);// 是黑瓷磚,且沒越界,沒計算過,則繼續以當前瓷磚為點,選中它周圍的瓷磚,進行搜尋
}
}
}
C++程式碼
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 25;
int dx[] = {0, 0, -1, 1};
int dy[] = {1, -1, 0, 0};
int n, m, ans = 0;
bool v[N][N];
char mp[N][N];
void dfs(int x, int y) {
v[x][y] = true;
ans ++;
for (int i = 0; i < 4; ++ i) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx < 0 || nx >= n || ny < 0 || ny >= m || v[nx][ny] == true || mp[nx][ny] == '#') continue;
dfs(nx, ny);
}
}
int main () {
while (true) {
cin >> m >> n;
if (n == 0 && m == 0) break;
ans = 0;
memset(v, 0, sizeof v);
int x, y;
for (int i = 0; i < n; ++ i) {
for (int j = 0; j < m; ++ j) {
cin >> mp[i][j];
if (mp[i][j] == '@') x = i, y = j;
}
}
dfs(x, y);
cout << ans << endl;
}
return 0;
}