PKU 3009 Curling 2.0(穷举搜索+剪枝)

题目链接 点击打开链接 

        题意是一块石子,从起始位置出发,题目中起始位置为2,每次移动,它会朝着某一个方向一直运动直到碰到墙或者滑出界外,或者到达终点(题目中是3表示);如果碰到墙,则相应的墙块消失,并且求停止在墙的前面一个位置,需要再次移动,直到到达目标位置。 每次移动石子,石子都会朝同一个方向移动,遇到下面情况就会停止:

         1.石子碰到墙块

         2.石子滑出界外

         3.石子到达终点

        现在要求石子从起点到达终点最少移动次数,如果移动次数大于10次或者无法移动到目标位置,则游戏失败,输出-1.  如图所示

                                                  
                                              
        改图中S表示其实位置,G表示终止位置,题目中,墙块以1表示,S用2表示,G用3表示,空白用0表示 球碰到墙后,墙块消失,并且球会停在墙块的前面一个位置,如图:
                                         

        图1到达目标位置情况如下图,右边为最后墙的状态。

        代码如下:

        由于题目中状态数最多为20*20,可以用穷举搜索,另外加了一个剪枝,就是当移动次数大于10搜索停止。

#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
#define H 22
#define W 22
#define INF 0xfffffff


int mp[H][W];
int dir[4][2] = {{1,0}, {0,1}, {-1,0}, {0,-1}};
int ans, m, n;

inline bool isWall(int x, int y)
{
	if (mp[x][y] == 1) return true;
	return false;
}

inline bool outBoard(int x, int y)
{
	if (x >= n || x < 0 || y >= m || y < 0)
		return true;
	return false;
}

inline bool target(int x, int y)
{
	if (mp[x][y] == 3)
		return true;
	return false;
}

void dfs(int x, int y, int cnt)
{
	if (cnt > 10 || cnt >= ans) return;

	for (int i=0; i<4; i++)
	{
		int tx = x, ty = y;

		if (outBoard(tx + dir[i][0], ty + dir[i][1]) || isWall(tx + dir[i][0], ty + dir[i][1])) 
			continue;

		while (!outBoard(tx, ty) && !isWall(tx, ty)	&& !target(tx, ty))
		{
			tx = tx + dir[i][0];
			ty = ty + dir[i][1];
		}

		if (outBoard(tx, ty)) continue;
		if (target(tx, ty)) 
		{
			if (cnt < ans) ans = cnt;
			return;
		}
		mp[tx][ty] = 0;
		dfs(tx-dir[i][0], ty-dir[i][1], cnt+1);
		mp[tx][ty] = 1;
	}



}

int main()
{

	while ( cin >> m >> n && m && n) 
	{
		for (int i=0; i<n; i++)
			for (int j=0; j<m; j++)
				cin >> mp[i][j];

		ans = INF;
		for (int i=0; i<n; i++)
			for (int j=0; j<m; j++)
				if (mp[i][j] == 2)
				{
					dfs(i, j, 1);
					break;
				}

		if (ans <= 10)
			cout << ans << endl;
		else 
			cout << -1 << endl;

	}
	return 0;
}


 

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值