Red and Black
There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A man is standing on a black tile. From a tile, he can move to one of four adjacent tiles. But he can't move on red tiles, he can move only on black tiles.
Write a program to count the number of black tiles which he can reach by repeating the moves described above.
Input:
The input consists of multiple data sets. A data set starts with a line containing two positive integers W and H; W and H are the numbers of tiles in the x- and y- directions, respectively. W and H are not more than 20.
There are H more lines in the data set, each of which includes W characters. Each character represents the color of a tile as follows.
'.' - a black tile
'#' - a red tile
'@' - a man on a black tile(appears exactly once in a data set)
The end of the input is indicated by a line consisting of two zeros.
Output:
For each data set, your program should output a line which contains the number of tiles he can reach from the initial tile (including itself).
Sample Input:
6 9 ....#. .....# ...... ...... ...... ...... ...... #@...# .#..#. 11 9 .#......... .#.#######. .#.#.....#. .#.#.###.#. .#.#..@#.#. .#.#####.#. .#.......#. .#########. ........... 11 6 ..#..#..#.. ..#..#..#.. ..#..#..### ..#..#..#@. ..#..#..#.. ..#..#..#.. 7 7 ..#.#.. ..#.#.. ###.### ...@... ###.### ..#.#.. ..#.#.. 0 0
Sample Output
45 59 6 13
这道题目要求求出可以走的地方(包括起点),如果用BFS做的话,可以先把起点入队列,并标记该点已经计数。然后,不断向外扩张,如果该点满足条件的话,那么就把该点放入队列中,再标记和计数...如此类推,直到找出所有满足条件的点。
代码如下:
import java.util.Scanner; public class Main { static class Location{ int x; int y; } public static void main(String[] args) { Scanner in = new Scanner(System.in); int W = in.nextInt(); int H = in.nextInt(); while(W != 0 || H != 0) { String[] str = new String[H]; for(int i = 0; i < H; i++) { str[i] = in.next(); } char[][] map = new char[H][W]; for(int r = 0; r < H; r++) { for(int c = 0; c < W; c++) { map[r][c] = str[r].charAt(c); } } boolean[][] visited = new boolean[H][W]; int result = BFS(map, visited, H, W); System.out.println(result); W = in.nextInt(); H = in.nextInt(); } } public static int BFS(char[][] map, boolean[][] visited, int H, int W) { int result = 0; Location[] queue = new Location[H*W+1]; int head = 0, tail = 0; for(int r = 0; r < H; r++) { for(int c = 0; c < W; c++) { if(map[r][c] == '@') { Location start = new Location(); start.y = r; start.x = c; queue[tail++] = start; visited[r][c] = true; result++; } } } int[] dx = {1, 0, -1, 0}; int[] dy = {0, -1, 0, 1}; while(head < tail) { Location curNode = queue[head++]; for(int d = 0; d < 4; d++) { Location next = new Location(); next.x = curNode.x + dx[d]; next.y = curNode.y + dy[d]; if(next.x >= 0 && next.x < W && next.y >= 0 && next.y < H) { if(map[next.y][next.x] == '.' && !visited[next.y][next.x]) { queue[tail++] = next; visited[next.y][next.x] = true; result++; } } } } return result; }
DFS的做法:
import java.util.Scanner; public class Main { static int result; public static void main(String[] args) { Scanner in = new Scanner(System.in); int W = in.nextInt(); int H = in.nextInt(); while(W != 0 || H != 0) { String[] str = new String[H]; for(int i = 0; i < H; i++) { str[i] = in.next(); } char[][] map = new char[H +1][W + 1]; int start_x = 0, start_y = 0; boolean[][] visited = new boolean[H + 1][W + 1]; for(int r = 0; r < H; r++) { for(int c = 0; c < W; c++) { map[r][c] = str[r].charAt(c); if(map[r][c] == '@') { start_x = c; start_y = r; visited[start_y][start_x] = true; } } } result = 0; DFS(map, visited, start_x, start_y, W, H); System.out.println(result); W = in.nextInt(); H = in.nextInt(); } } public static void DFS(char[][] map, boolean[][] visited, int cur_x,int cur_y, int W, int H) { if(map[cur_y][cur_x] == '#') { return; } result++; int[] dx = {1, 0, -1, 0}; int[] dy = {0, -1, 0, 1}; for(int i = 0; i < 4; i++) { int x = cur_x + dx[i]; int y = cur_y + dy[i]; if(x >= 0 && x < W && y >= 0 &&y < H) { if(!visited[y][x]) { visited[y][x] = true; DFS(map, visited, x, y, W, H); //visited[y][x] = false; } } } } }