POJ 1979 Red and Black (回溯)
| Descirbe: |
| 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 |
题目传送门:POJ 1979
题目大意:
(翻译有限,凑合着看)
有一个棋盘,上面有黑的,又红的,现在你站在一个黑块上,只能往前后左右四个位置走,并且不能踩红块,黑块只能走一次,问总共能走多少黑块
解题思路:
比较典型的回溯法,用二维字符数组存入棋盘,递归搜索,如果符合条件,就继续递归,否则回溯,每一次踩到黑块就ans+1.
AC代码:
1 #include <stdio.h> 2 #include <iostream> 3 #include <cstring> 4 using namespace std; 5 char s[25][25]; // 二维数组存棋盘 6 int f[25][25]; // 标志数组,存是否走过这里的信息 7 int w,h,x,y; // 列,行,起始位置x,y 8 int ans; // 走过的黑块数 9 void Search(int m, int n) 10 { 11 f[m][n] = 1; // 标志这个地方已经走过 12 ans++; // 块数加一,初始地方也是黑的,也要加一 13 // 只要没有出界,并且是黑块,也没有走过,就可以走,继续搜索 14 if(m+1 <= h && s[m+1][n] == '.' && f[m+1][n] == 0) Search(m+1,n); 15 if(m-1 >= 1 && s[m-1][n] == '.' && f[m-1][n] == 0) Search(m-1,n); 16 if(n+1 <= w && s[m][n+1] == '.' && f[m][n+1] == 0) Search(m,n+1); 17 if(n-1 >= 1 && s[m][n-1] == '.' && f[m][n-1] == 0) Search(m,n-1); 18 } 19 int main() 20 { 21 s[0][0] = 0; // 下标从1开始,0下标特殊处理一下 22 while(~scanf("%d%d",&w,&h) && w+h) 23 { 24 memset(f,0,sizeof(f)); // 初始全部为未走过 25 ans = 0; // 注意,每个样例要先初始化答案 26 for(int i = 1; i <= h; i++) 27 { 28 for(int j = 1; j <= w; j++) 29 { 30 //读入答案,因为总是读入换行之类的其他字符,所以用此方法 31 // 感觉这样麻烦了,应该有更好办法 32 scanf("%c",&s[i][j]); 33 if(s[i][j] == '@' || s[i][j] == '.' || s[i][j] == '#') continue; 34 else scanf("%c",&s[i][j]); 35 // 如果在这里就找到初始位置'@',并记录下来的话,会出错, 36 // 暂时不知道为什么,就重新扫面一边 37 } 38 } 39 // 扫描,找到起始位置,坑爹就坑爹到这了,解决了好长时间 40 for(int i = 1; i <= h; i++) 41 { 42 for(int j = 1; j <= w; j++) 43 { 44 if(s[i][j] == '@') 45 { 46 x = i; 47 y = j; 48 } 49 }
50 } 51 //进入函数 52 Search(x,y); 53 printf("%d\n",ans); // 打印答案 54 } 55 return 0; 56 }
小结:
回溯算是搜索的一种方式吧,有个初始条件,或者初始状态,开始在一定范围,一定条件下搜索,如果满足条件了,就记录下来,否则,如果出界了,或者违规了,就回溯,继续搜索。

浙公网安备 33010602011771号