题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1312
此题条件编译的使用值得借鉴
#if ONLINE_JUDGE
// 从io输入
#endif
#ifndef ONLINE_JUDGE
// 从文件输入
#endif
1312: Red and Black
Time Limit: 2000/1000 MS(Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Problem Description
There is a rectangular room, covered withsquare tiles. Each tile is colored either red or black. A man is standing on ablack tile. From a tile, he can move to one of four adjacent tiles. But hecan'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 byrepeating the moves described above.
Input
The input consists of multiple data sets. Adata set starts with a line containing two positive integers W and H; W and Hare the numbers of tiles in the x- and y- directions, respectively. W and H arenot 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)
Output
For each data set, your program should outputa 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
-----------------------------------------------------
解题思路
深度优先搜索,用栈的数据结构,注意核心代码各条语句的顺序
PS. C++里栈的数据结构vector比stack好用,vector有push_back(对应stack.push)和pop_back(对应stack.pop),stack相比vector还少了clear方法
核心代码
while (!path.empty()) // 如果栈不空
{
pos = path.back(); // 取栈顶的点
while (surround(mat,m,n)); // 搜索旁边的'.'并移动一格直到不能移动
path.pop_back(); // 退一步,该点出栈,再次回到栈空判断
}
-----------------------------------------------------
代码
#include<iostream>
#include<fstream>
#include<vector>
using namespace std;
// 矩阵中节点
struct node {
int i;
int j;
};
// 其实应该是“运动的小人类”
class point {
public:
node pos;
vector<node> path;
int cnt;
point(int si, int sj)
{
pos.i = si;
pos.j = sj;
path.push_back(pos);
cnt = 1;
}
// 向上/下/左/右移动一格,如果周边没有'.',则返回false,否则返回true
bool surround(char **mat, int m, int n)
{
if (pos.i>0 && mat[pos.i-1][pos.j] == '.')
{
pos.i--;
}
else if (pos.i<m-1 && mat[pos.i+1][pos.j] == '.')
{
pos.i++;
}
else if (pos.j>0 && mat[pos.i][pos.j-1] == '.')
{
pos.j--;
}
else if (pos.j<n-1 && mat[pos.i][pos.j+1] == '.')
{
pos.j++;
}
else
{
return false;
}
mat[pos.i][pos.j] = '@';
path.push_back(pos);
cnt++;
return true;
}
void start(char **mat, int m, int n)
{
// 深搜核心代码(注意各语句的顺序)
while (!path.empty()) // 如果栈不空
{
pos = path.back(); // 取栈顶的点
while (surround(mat,m,n)); // 搜索旁边的'.'并移动一格直到不能移动
path.pop_back(); // 退一步,该点出栈,再次回到栈空判断
}
}
};
int main()
{
int m = 1, n = 1, i = 0, j = 0;
int cnt = 1; // '.'计数器
int si = 0, sj = 0;
#if ONLINE_JUDGE
cin >> n >> m;
while (m && n)
{
cnt = 1;
char **mat = new char*[m];
for (i=0; i<m; i++)
{
mat[i] = new char[n];
}
for (i=0; i<m; i++)
{
for (j=0; j<n; j++)
{
cin >> mat[i][j];
if (mat[i][j]=='@')
{
si = i;
sj = j;
}
}
}
point mypoint(si,sj);
mypoint.start(mat,m,n);
cout << mypoint.cnt << endl;
for (i=0; i<m; i++)
{
delete[] mat[i];
}
delete[] mat;
cin >> n >> m;
}
#endif // ONLINE_JUDGE
#ifndef ONLINE_JUDGE
ifstream fin("hdu1312.txt");
fin >> n >> m;
while (m && n)
{
cnt = 1;
char **mat = new char*[m];
for (i=0; i<m; i++)
{
mat[i] = new char[n];
}
for (i=0; i<m; i++)
{
for (j=0; j<n; j++)
{
fin >> mat[i][j];
if (mat[i][j]=='@')
{
si = i;
sj = j;
}
}
}
point mypoint(si,sj);
mypoint.start(mat,m,n);
cout << mypoint.cnt << endl;
for (i=0; i<m; i++)
{
delete[] mat[i];
}
delete[] mat;
fin >> n >> m;
}
fin.close();
#endif // local
}