(水)POJ-3009 DFS+回溯

题目大意:给一个n*m的图,给定起点及目的地,每次往某个方向滑动后只有撞到石头才会停下,且石头会被撞毁,如果出界则不能这样走。问做少滑动多少次能到目的地,且限制了最多滑10次(用来剪枝)(注意,滑动次数不是指走一格算一次,还是从开始滑动到停下才算一次)

题目链接:点击打开链接

分析:用dfs,每次枚举4个方向,若没有停下则一直前进直到停下进入下一次递归,同时记录下被撞到的石头被摧毁,返回时再将此石头恢复就行(利用回溯的思想),若出界则此方向不能走continue就行

直接上代码:

#include<cstdio>                 //POJ3009 dfs+经典回溯
#include<algorithm>
using namespace std;
#define Max 20+5
#define Minus_1 -1
int a[Max][Max];
int sx, sy, ex, ey, ans = 11;
struct point
{
	int first, second;
}p[4] = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
void dfs(int x, int y, int step, int turn)
{
	if (step > 10) return;
	for (int i = 0; i < 4; i++)       //枚举4个方向
	{
		int flag = 0;
		int r = x + p[i].first, v = y + p[i].second;
		flag++;
		while (a[r][v] == 0) { r = r + p[i].first; v = v + p[i].second; flag++; }  //只要此方向下一格为0,就一直往此方向走
		if (a[r][v] == 1 && flag > 1)
		{
			a[r][v] = 0;
			dfs(r - p[i].first, v - p[i].second, step + 1, i);
			a[r][v] = 1;
		}
		if (a[r][v] == Minus_1) continue;
		if (a[r][v] == 3 && step + 1 < ans) { ans = step + 1; return; }
	}
	return;
}
int main()
{
	int W, H;
	while (scanf("%d%d", &W, &H))
	{
		if (W == 0 && W == 0) break;
		ans = 11;
		memset(a, Minus_1, sizeof(a));
		for (int i = 1; i <= H; i++)
			for (int j = 1; j <= W; j++)
			{
			scanf("%d", &a[i][j]);
			if (a[i][j] == 2) { sx = i, sy = j; }
			if (a[i][j] == 3) { ex = i, ey = j; }
			}
		a[sx][sy] = 0;
		dfs(sx, sy, 0, 4);
		printf("%d\n", ans <= 10 ? ans : -1);
	}
	return 0;
}


你可能感兴趣的:(ACM,DFS,回溯,题解报告)