dfs 经典题目之 "POJ 1979: Red and Black" "POJ 3009: Curling 2.0"

做了两道dfs的题,看到题目后,先想想了自己的思路,然后去看看大神们有没有关于这道题的博客,看看他们的思路是怎样的。果然,大神们的思路总是那么的犀利,其实这些题都是DFS的题目,形式都比较固定,关键是学习一些细节方面的处理。所以我们能做的,就是学习人家的技巧、优秀的思路,总结,归纳。其实这些题都是DFS的题目,形式都比较固定,关键是学习一些细节方面的处理。相信有一天自己再看到这类题目的时候也会想到这些方法的。所以在此贴出代码,希望大家一同进步!

Red and Black
Time Limit: 1000MS Memory Limit: 30000K
Total Submissions: 22831 Accepted: 12315

Description

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
//From Big_Heart 
//这是一道很基本的DFS,注意理解细节处理 
#include <iostream>
//#include <fstream>
using namespace std;
void bfs(int x, int y);
int go[][2] = { 0, -1, 0, 1, -1, 0, 1, 0 };
int n, m, B_x, B_y, count_;
char map[21][21];
int main(){
	//ifstream in;
	//in.open("C:\\a.txt");
	//if (in){
		while (1){
			cin >> m >> n;		//n行m列
			if (n == 0 && m == 0)
				break;
			count_ = 1;
			for (int i = 0; i < n; i++){
				for (int j = 0; j < m; j++){
					cin >> map[i][j];
					if (map[i][j] == '@')
						B_x = i, B_y = j;
				}
			}
			bfs(B_x, B_y);
			cout <<count_ << endl;
		//}
		//}
		//else
		//cout << "Wrong Input";
		//in.close();

	}
}
void bfs(int x, int y){
	map[x][y] = '#';
	for (int i = 0; i < 4; i++)
	if ((map[x + go[i][0]][y + go[i][1]] == '.') && x + go[i][0] >= 0 && x + go[i][0] < n&&y + go[i][1] >= 0 && y + go[i][1] < m){
		map[x + go[i][0]][y + go[i][1]] = '#';
		bfs(x + go[i][0], y + go[i][1]);
		count_++;
	}
}


Curling 2.0
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 11907 Accepted: 5041

Description

On Planet MM-21, after their Olympic games this year, curling is getting popular. But the rules are somewhat different from ours. The game is played on an ice game board on which a square mesh is marked. They use only a single stone. The purpose of the game is to lead the stone from the start to the goal with the minimum number of moves.

Fig. 1 shows an example of a game board. Some squares may be occupied with blocks. There are two special squares namely the start and the goal, which are not occupied with blocks. (These two squares are distinct.) Once the stone begins to move, it will proceed until it hits a block. In order to bring the stone to the goal, you may have to stop the stone by hitting it against a block, and throw again.


Fig. 1: Example of board (S: start, G: goal)

The movement of the stone obeys the following rules:

  • At the beginning, the stone stands still at the start square.
  • The movements of the stone are restricted to x and y directions. Diagonal moves are prohibited.
  • When the stone stands still, you can make it moving by throwing it. You may throw it to any direction unless it is blocked immediately(Fig. 2(a)).
  • Once thrown, the stone keeps moving to the same direction until one of the following occurs:
    • The stone hits a block (Fig. 2(b), (c)).
      • The stone stops at the square next to the block it hit.
      • The block disappears.
    • The stone gets out of the board.
      • The game ends in failure.
    • The stone reaches the goal square.
      • The stone stops there and the game ends in success.
  • You cannot throw the stone more than 10 times in a game. If the stone does not reach the goal in 10 moves, the game ends in failure.


Fig. 2: Stone movements

Under the rules, we would like to know whether the stone at the start can reach the goal and, if yes, the minimum number of moves required.

With the initial configuration shown in Fig. 1, 4 moves are required to bring the stone from the start to the goal. The route is shown in Fig. 3(a). Notice when the stone reaches the goal, the board configuration has changed as in Fig. 3(b).


Fig. 3: The solution for Fig. D-1 and the final board configuration

Input

The input is a sequence of datasets. The end of the input is indicated by a line containing two zeros separated by a space. The number of datasets never exceeds 100.

Each dataset is formatted as follows.

the width(=w) and the height(=h) of the board 
First row of the board
 
... 
h-th row of the board

The width and the height of the board satisfy: 2 <= w <= 20, 1 <= h <= 20.

Each line consists of w decimal numbers delimited by a space. The number describes the status of the corresponding square.

0vacant square
1block
2start position
3goal position

The dataset for Fig. D-1 is as follows:

6 6 
1 0 0 2 1 0 
1 1 0 0 0 0 
0 0 0 0 0 3 
0 0 0 0 0 0 
1 0 0 0 0 1 
0 1 1 1 1 1

Output

For each dataset, print a line having a decimal integer indicating the minimum number of moves along a route from the start to the goal. If there are no such routes, print -1 instead. Each line should not have any character other than this number.

Sample Input

2 1
3 2
6 6
1 0 0 2 1 0
1 1 0 0 0 0
0 0 0 0 0 3
0 0 0 0 0 0
1 0 0 0 0 1
0 1 1 1 1 1
6 1
1 1 2 1 1 3
6 1
1 0 2 1 1 3
12 1
2 0 1 1 1 1 1 1 1 1 1 3
13 1
2 0 1 1 1 1 1 1 1 1 1 1 3
0 0

Sample Output

1
4
-1
4
10
-1

//From Big_Heart
//原本看到这道题的时候是考虑用数组存储状态的,但要是数组很大的话,有可能会内存不足;看了别人的代码后,突然觉得自己好low  ==  ,他使用一个很完美的//方法来解决数组状态变化的情况
#include <iostream>
#include<queue>
#include<cmath>
//#include <fstream>
using namespace std;
void dfs(int x, int y, int step);
int go[][2] = { 0, -1, 0, 1, -1, 0, 1, 0 };//left,right,up,down
int n, m, B_x, B_y, min_r;
int map[21][21];
int main(){
	//ifstream in;
	//in.open("C:\\a.txt");
	//if (in){
		while (1){
			cin >> m >> n;		//n行m列
			if (n == 0 && m == 0)
				break;
			min_r = 0x03F3F3F;
			for (int i = 0; i < n; i++){
				for (int j = 0; j < m; j++){
					cin >> map[i][j];
					if (map[i][j] == 2)
						B_x = i, B_y = j;
				}
			}
			map[B_x][B_y] = 0;
			dfs(B_x, B_y, 1);
			if (min_r < 11)
				cout << min_r << endl;
			else
				cout << -1 << endl;
		}
	}
	//else
		//cout << "Wrong Input";
	//in.close();
//}
void dfs(int x, int y, int step){
	if (step > 10)
		return;
	for (int i = 0; i < 4; i++){
		int x_ = x, y_ = y;
		x_ += go[i][0], y_ += go[i][1];
		if (map[x_][y_] == 1) continue;                     //即起点的某边为 1,则不能往这方向走了
		while (map[x_][y_] == 0 ){                          //一直往某方向走,当出界或碰到某点不为 0 时,跳出
			x_ += go[i][0];
			y_ += go[i][1];
			if (x_ < 0 || x_ > n || y_ < 0 || y_ > m)   //出界就不去算了
				break;
		}
		if (x_ >= 0 && x_ < n&&y_ >= 0 && y_<m){		// 没出界
			if (map[x_][y_] == 3){                 //当碰到的是目的地时
				if (min_r>step)
					min_r = step;
			}
			else if (map[x_][y_] == 1){            //当碰到的是 1 时
				map[x_][y_] = 0;
				dfs(x_-go[i][0], y_-go[i][1], step+1);  // 继续DFS
				map[x_][y_] = 1;
			}
		}
	}
	return;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值