POJ3009 Curling 2.0 DFS 深搜

题目大意:地图上“0”代表空白可滑动区域,“1”代表阻碍物,“2”代表起点,“3”代表终点。冰壶从起点开始可以朝上下左右四个方向滑动,若没有遇到阻碍物或者没有到达终点则不会停止,直到滑出地图。若遇到阻碍物后冰壶会停止在阻碍物前一格,被碰撞的阻碍物会消失。需要注意的是,若在冰壶旁边有障碍物,则不可朝障碍物一侧滑动。求冰壶到达终点的最短滑动次数。若10次滑动不能到达终点,则视为不能到达,输出-1。

思路:用简单的DFS即可完成此题,除此以外还可以用迭代深搜来解决。此处贴出最简单的DFS以供参考。

#include <stdio.h>
#include <iostream>
#include <vector>

using namespace std;
int W,H,sum,end_i,end_j;							//W:行	H:列	sum:答案	end_i:终点行 end_j:终点列
int vec[20][20];								//地图
int writeans(int dep)								//将某分支深度与现有答案比较
{
	if(dep == -1)
		return 0;
	if(sum == -1 || sum > dep)						//某分支深度小于现有答案则更新答案
		sum = dep;
	return 0;
}
int dfs(int m_i, int m_j, int m_vec[20][20], int dep)
{
	if(dep > 10 || (sum != -1 && dep > sum))		//剪枝,步数大于10或者步数大于现有解步数则退出
		return 0;
	int mm_vec[20][20];
	for(int i = 0; i < H; i++)						//复制二维数组
			for(int j = 0; j < W; j++)
				mm_vec[i][j] = m_vec[i][j];
	for(int k = 0; k < 4; k++)						//超某一方向查看是否可滑动
	{
		int flag = -1;
		int next_i,next_j;
		for(int l = 1; l < 20; l++)
		{
			switch(k)
			{
				case 0:	next_i = m_i - l;	next_j = m_j;	break;
				case 1:	next_i = m_i + l;	next_j = m_j;	break;
				case 2:	next_i = m_i;	next_j = m_j - l;	break;
				case 3:	next_i = m_i;	next_j = m_j + l;	break;
				default:	break;
			}
			if(next_i < 0 || next_i >= H || next_j < 0 || next_j >= W || (l == 1 && mm_vec[next_i][next_j] == 1))	//需要注意的是,若在冰壶旁边有障碍物,则不可朝障碍物一侧滑动
				break;
			else if(mm_vec[next_i][next_j] == 3)	//若遇到终点,则记录答案
			{
				writeans(dep);
				return 0;
			}
			else if(l != 1 && mm_vec[next_i][next_j] == 1)
			{
				mm_vec[next_i][next_j] = 0;
				flag = k;
				switch(k)
				{
					case 0: next_i += 1;	break;
					case 1:	next_i -= 1;	break;
					case 2:	next_j += 1;	break;
					case 3:	next_j -= 1;	break;
					default:	break;
				}
				break;
			}	
		}
		if(flag != -1)
		{
			dfs(next_i , next_j, mm_vec, dep + 1);
			switch(k)								//还原地图
			{
				case 0: next_i -= 1;	break;
				case 1:	next_i += 1;	break;
				case 2:	next_j -= 1;	break;
				case 3:	next_j += 1;	break;
				default:	break;
			}
			mm_vec[next_i][next_j] = 1;	
		}
		
	}
	return 0;
}

int main()
{
	while(1)
	{
		cin >> W >> H;
		if(W == 0 && H == 0)
			break;
		sum=-1;
		int tmp_i;
		int start,end;
		for(int i = 0; i < H; i++)
			for(int j = 0; j < W; j++)
			{
				cin >> tmp_i;
				vec[i][j] = tmp_i;
				if(tmp_i == 2)						//记录起点
				{
					start = i;
					end = j;
				}
				if(tmp_i == 3)						//记录终点
				{
					end_i = i;
					end_j = j;
				}
			}
		dfs(start, end, vec, 1);
		cout << sum << endl;
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值