问题重述
问题描述:
有一个长方形的房间里,是用方瓦覆盖的。每个方瓦的颜色是红色或黑色。一名男子正站在一个黑色瓷砖。他从他所站的方瓦上,可以转移到相邻的四个砖之一。但他无法进入红瓦,他只可以进入黑瓦。
编写一个程序来计算黑瓦数量,也就是他可以达到的方瓦数(重复上述动作)。输入:
输入包含多个数据集。一个数据集的包含有在开始的第一行的两个正整数W和H,W和H表示x和y方向上的方瓦数。 W和H的不超过20。之后有H行的数据集,其中每行包括W列字符。每个字符代表着瓷砖的颜色如下:
’.’ -黑色瓦片
‘#’-一个红色的瓷砖
‘@’-一黑砖上的人
该程序可以循环输入,当输入的W和H都为0时,程序终止。
输出:
有多少块黑瓦
Sample Input
6 9
....#.
.....#
......
......
......
......
......
#@...#
.#..#.
11 9
.#.........
.#.#######.
.#.#.....#.
.#.#.###.#.
.#.#..@#.#.
.#.#####.#.
.#.......#.
.#########.
...........
11 6
..#..#..#..
..#..#..#..
..#..#..###
..#..#..#@.
..#..#..#..
..#..#..#..
7 7
..#.#..
..#.#..
###.###
...@...
###.###
..#.#..
..#.#..
0 0
Sample Output
45
59
6
13
解题过程:
分析过程:
当读懂了题意后,很容易地就地发现这是一道典型的深度遍历的应用。所以在算法上就没有什么问题。当前要解决的就是数据的输入与存储处理问题。一看到矩阵的输入,我就想到了要用二维数组,然后对应的把字符转换为数字存储。考虑到在遍历过程中要判断边界问题,所以我就把数组的行列数再多加两行两列,以方便处理。
编程过程:
在数据的输入方面,我花了较长的时间,我刚开始是用scanf("%s",s);想把每一行的字符读取后,再去掉空格,最后再存进数组。但却发现是这种方式是不读取空格的。之后又想用gets(s);但发现去空格有点麻烦。最后才发现用getchar();就可以很简单地实现。
在数据的存储方面,我用二维数组存储对应的数字,并设置数组初始值为0;因为边界问题,我直接空出一圈不存储数据,使其为默认值,使得边界的处理变很很简单。
在调试的过程中,我犯了一些很低级的错误,花费了很多的时间。其一,break;只跳出当前循环,但我却在一个二层循环中直接使用,以为能跳出两层。其二,因为是循环输入与输出,需要每一趟都初始化。其三,遍历的时候是四个方向逐个访问,但我却因为顺手就用了else if,使得只访问一个方向。
做题收获:
此次编程,让我对字符串的输入处理更熟练,对二维数组做为函数参数的理解更深刻,对广度遍历的算法也更进一步掌握。
4.程序源码:
问题描述:
有一个长方形的房间里,是用方瓦覆盖的。每个方瓦的颜色是红色或黑色。一名男子正站在一个黑色瓷砖。他从他所站的方瓦上,可以转移到相邻的四个砖之一。但他无法进入红瓦,他只可以进入黑瓦。
编写一个程序来计算黑瓦数量,也就是他可以达到的方瓦数(重复上述动作)。输入:
输入包含多个数据集。一个数据集的包含有在开始的第一行的两个正整数W和H,W和H表示x和y方向上的方瓦数。 W和H的不超过20。之后有H行的数据集,其中每行包括W列字符。每个字符代表着瓷砖的颜色如下:
’.’ -黑色瓦片
‘#’-一个红色的瓷砖
‘@’-一黑砖上的人
该程序可以循环输入,当输入的W和H都为0时,程序终止。
输出:
有多少块黑瓦
Sample Input
6 9
....#.
.....#
......
......
......
......
......
#@...#
.#..#.
11 9
.#.........
.#.#######.
.#.#.....#.
.#.#.###.#.
.#.#..@#.#.
.#.#####.#.
.#.......#.
.#########.
...........
11 6
..#..#..#..
..#..#..#..
..#..#..###
..#..#..#@.
..#..#..#..
..#..#..#..
7 7
..#.#..
..#.#..
###.###
...@...
###.###
..#.#..
..#.#..
0 0
Sample Output
45
59
6
13
解题过程:
分析过程:
当读懂了题意后,很容易地就地发现这是一道典型的深度遍历的应用。所以在算法上就没有什么问题。当前要解决的就是数据的输入与存储处理问题。一看到矩阵的输入,我就想到了要用二维数组,然后对应的把字符转换为数字存储。考虑到在遍历过程中要判断边界问题,所以我就把数组的行列数再多加两行两列,以方便处理。
编程过程:
在数据的输入方面,我花了较长的时间,我刚开始是用scanf("%s",s);想把每一行的字符读取后,再去掉空格,最后再存进数组。但却发现是这种方式是不读取空格的。之后又想用gets(s);但发现去空格有点麻烦。最后才发现用getchar();就可以很简单地实现。
在数据的存储方面,我用二维数组存储对应的数字,并设置数组初始值为0;因为边界问题,我直接空出一圈不存储数据,使其为默认值,使得边界的处理变很很简单。
在调试的过程中,我犯了一些很低级的错误,花费了很多的时间。其一,break;只跳出当前循环,但我却在一个二层循环中直接使用,以为能跳出两层。其二,因为是循环输入与输出,需要每一趟都初始化。其三,遍历的时候是四个方向逐个访问,但我却因为顺手就用了else if,使得只访问一个方向。
做题收获:
此次编程,让我对字符串的输入处理更熟练,对二维数组做为函数参数的理解更深刻,对广度遍历的算法也更进一步掌握。
4.程序源码:
package middle;
import java.io.BufferedInputStream;
import java.util.Scanner;
/**
*
*poj1979
* 这道题是数据结构的第一道,刚开始是用c语言做的,但后来其他题目我都用了java去写,
* 所以现在只是简单把c语法转化为java法,统一一下编码而已
* @author NC
*/
public class Poj1979 {
private final static int MAXCOL = 22;
private final static int MAXROW = 22;
private static int[][] floor = new int[MAXROW][MAXCOL]; //最多是20行,20列,再加两行两列作为边界
private static int[][] visited = new int[MAXROW][MAXCOL]; //标记是否访问过,默认没有访问过
public static void main(String[] args) {
Scanner scan = new Scanner(new BufferedInputStream(System.in));
while (scan.hasNext()) {
int col = scan.nextInt();
int row = scan.nextInt();
int i = 0, j = 0, k = 0;
int count = 0;
int flag = 0;
char c;
//读取数据
if (col == 0 && row == 0) {
break;
}
//因为是循环输入,所以每一次都得初始化
for (i = 0; i < MAXROW; i++) {
for (j = 0; j < MAXCOL; j++) {
floor[i][j] = 0;
visited[i][j] = 0;
}
}
scan.nextLine();
//一个一个读取字符,将符号转换为数字
for (i = 1; i <= row; i++) {
char[] ss = scan.nextLine().trim().toCharArray();
for (j = 1; j <= col; j++) {
while (true) {
c = ss[j-1];
if (c == '.' || c == '#' || c == '@') {
break;
}
}
if (c == '.') {
floor[i][j] = 1;
} else if (c == '#') {
floor[i][j] = 2;
} else if (c == '@') {
floor[i][j] = 3;
}
}
}
//找出人所站的位置
flag = 0;
for (i = 1; i <= row; i++) {
for (j = 1; j <= col; j++) {
if (floor[i][j] == 3) {
flag = 1;
break; //要跳出两层
}
}
if (flag == 1) {
break;
}
}
//深度遍历
if (floor[i][j] == 3) {
DFS(i, j);
}
//count the number of tiles he can reach from the initial tile
count = 0;
for (i = 1; i <= row; i++) {
for (j = 1; j <= col; j++) {
if (visited[i][j] == 1) {
count++;
}
}
}
//print the number of tiles he can reach from the initial tile
System.out.println(count);
}
}
static void DFS(int i, int j) {
//标记访问过
visited[i][j] = 1;
//四个方向都要遍历,不能用else if
if (floor[i][j + 1] == 1 && visited[i][j + 1] == 0) {
DFS(i, j + 1);
}
if (floor[i][j - 1] == 1 && visited[i][j - 1] == 0) {
DFS(i, j - 1);
}
if (floor[i + 1][j] == 1 && visited[i + 1][j] == 0) {
DFS(i + 1, j);
}
if (floor[i - 1][j] == 1 && visited[i - 1][j] == 0) {
DFS(i - 1, j);
}
}
}