POJ 3009 DFS +剪枝

本文介绍了一道经典的深度优先搜索(DFS)算法题,通过分析迷宫中小球的移动路径来找出最少移动次数到达出口的方法。文章给出了详细的代码实现,并讨论了剪枝技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目在http://poj.org/problem?id=3009

因为DFS写的不多,所以这个看似很简单的题目,居然修改补补搞了3个多小时,哎。


题目大意是说在一个迷宫中,我们的小球从起点出发,然后只能被横向和竖向抛出,如果打到障碍物,小球就会停止,同时障碍物也会被击碎。

小球可以抛掷一个方向的前提是:它的前面没有障碍物。

如果小球出界或者抛出次数大于10 都是失败。

例如开始状态是:



小球经过四次抛掷,到达状态:



这样就是成功了。



解答:

题目是明显的DFS,给定其中的一点,然后朝着四个方向搜索,找到一个合适的下一个位置,然后再重复上面的过程。

其中有两处可以做剪枝,一个是 当前的steps数目大于10,另一处是如果当前遍历的steps已经比之前求出来的最小值大,那么则跳过这次遍历。


程序要求求出最小的抛掷次数,可以到达出口。

#include <stdio.h>
#include <memory.h>
#define MAX_GRID 21
int min(int x, int y)
{
	return x>y?y:x;
}
struct Grid
{
	int r;
	int c;

	bool operator == (const Grid &b)const
	{
		return r == b.r && c == b.c;
	}
	bool operator != (const Grid &b)const
	{
		return !(*this == b);
	}
};

int g_Board[MAX_GRID][MAX_GRID];
int g_nRow, g_nCol;

void DfsSearch(const Grid &start, int steps, int &minSteps)
{

	steps ++;
	if(steps > 10)
	{
		return ;
	}
	//search for four direction;

	//search up:
	Grid iMove;
	Grid newMove;
	for( iMove = start, iMove.r-- ; iMove.r >= 0; iMove.r--)
	{
		if(iMove.r == start.r - 1 && g_Board[iMove.r][iMove.c] == 1)
		{
			break;
		}
		if(g_Board[iMove.r][iMove.c] == 3 )
		{
			minSteps = min(minSteps, steps);
			return ;
		}
		if(g_Board[iMove.r][iMove.c] == 1 && steps < minSteps)
		{
			g_Board[iMove.r][iMove.c] = 0;
			newMove = iMove;
			newMove.r++;
			DfsSearch(newMove, steps, minSteps);
			g_Board[iMove.r][iMove.c] = 1;
			break;
		}
	}

	//search down;
	for( iMove = start, iMove.r += 1; iMove.r < g_nRow; iMove.r++)
	{
		if(iMove.r == start.r + 1 && g_Board[iMove.r][iMove.c] == 1)
		{
			break;
		}
		if(g_Board[iMove.r][iMove.c] == 3)
		{
			minSteps = min(minSteps, steps);
			return ;
		}
		if(g_Board[iMove.r][iMove.c] == 1 && steps < minSteps)
		{
			g_Board[iMove.r][iMove.c] = 0;
			newMove = iMove;
			newMove.r--;
			DfsSearch(newMove, steps, minSteps);
			g_Board[iMove.r][iMove.c] = 1;
			break;

		}
		
	}
	//search left
	for( iMove = start, iMove.c-- ; iMove.c >= 0; iMove.c--)
	{
		if(iMove.c == start.c - 1 && g_Board[iMove.r][iMove.c] == 1)
		{
			break;
		}
		if(g_Board[iMove.r][iMove.c] == 3)
		{
			minSteps = min(minSteps, steps);
		}
		if(g_Board[iMove.r][iMove.c] == 1 && steps < minSteps)
		{
			g_Board[iMove.r][iMove.c] = 0;
			newMove = iMove;
			newMove.c++;
			DfsSearch(newMove, steps, minSteps);
			g_Board[iMove.r][iMove.c] = 1;
			break;

		}

	}
	//search right
	for( iMove = start, iMove.c++ ; iMove.c < g_nCol; iMove.c++)
	{
		if(iMove.c == start.c + 1 && g_Board[iMove.r][iMove.c] == 1)
		{
			break;
		}
		if(g_Board[iMove.r][iMove.c] == 3)
		{
			minSteps = min(minSteps, steps);
		}
		if(g_Board[iMove.r][iMove.c] == 1 && steps < minSteps)
		{
			g_Board[iMove.r][iMove.c] = 0;
			newMove = iMove;
			newMove.c--;
			DfsSearch(newMove, steps, minSteps);
			g_Board[iMove.r][iMove.c] = 1;
			break;

		}
	}
	steps--;
}
int main()
{
	int i,j,k;
	while(scanf("%d%d", &g_nCol, &g_nRow) != EOF)
	{
		memset(g_Board, 0, sizeof(g_Board));
		if(g_nRow == 0 && g_nCol == 0)
		{
			break;
		}
		Grid start, end;
		for(  i = 0; i < g_nRow; i++)
		{
			for( j = 0; j < g_nCol; j++)
			{
				scanf("%d", &k);
				g_Board[i][j] = k;
				if( k == 2)
				{
					start.r = i;
					start.c = j;
				}
				else if( k == 3)
				{
					end.r = i;
					end.c = j;
				}
			}

		}
		int minSteps = 100000000;
		DfsSearch(start, 0, minSteps);
		if(minSteps == 100000000)
		{
			printf("-1\n");
		}
		else
		{

			printf("%d\n", minSteps);
		}

	}
	return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值