poj 3009 冰壶

题目 描述:


MM -21星球上的冰壶比赛规则如下:比赛的目标是将一个冰壶从起始位置移动到终点 。比赛在画有方格的冰面上进行,每移动 一个算一步,移动 步数少者获胜。
上图是一个比赛场地的样例,样例,场地中一些地方有障碍物,起始位置标记 为 S,目标位置标记 为 G。冰壶每次移动, 必须 撞到障碍物才能停止,待冰壶停止之后运动员才能进行下一次移动 。
移动规则如下:
⚫ 初始状态冰壶在起始位置
⚫ 冰壶只能向上或者向下移动,不能斜向移动
⚫ 冰壶完全停下来,你才能再次移动它
⚫ 每次移动, 冰壶必须满足以下条件之一才能停下 来:
 冰壶撞到障碍物
◆冰壶停在障碍物旁边
◆ 障碍物消失
冰壶 出界
◆ 比赛结束, 失败
冰壶到达目标状态
◆ 比赛结束,胜利
在比赛规则下,请判断是否可以获胜,如果可以,输出最少操作次数。
例如,在下图所示状态下,需要通过4次移动到达终点, 移动后比赛场地状态 如图 b。


输入 描述 :


输入包含多组测试样例,样例组数小于100 ,当样例输入两个0时输入结束
每组样例第一行输入场地的宽 w和高 h 2 <= w <=20,1 <= h<= 20。
以下h行每行包含 w个数字,数字,每个 数字含义为:
0 空地
1 障碍
2 起始位置
3 终止位置


输出描述 :


对于 每组 数据,输出 从起始点到终点 的最少移动次数,如果无法到达,输出 -1。


输入 样例: 


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

输出样例:

1
4
-1
4
10
-1


思路:

直接dfs向四个方向搜索 暴力搞定

#include<iostream>
using namespace std;
int w,h,a[21][21],x1,y1,minn,flag;
void dfs(int x,int y,int bushu) {
	if(bushu>=minn) {//小剪枝
		return;
	}
	for(int i=x+1; i<=w; i++) {//从x+1开始往右搜
		if(a[x+1][y]==1)break;//如果旁边的格子有障碍物,停止
		if(a[i][y]==1) {//搜到第一个障碍物
			a[i][y]=0;//障碍物归0
			dfs(i-1,y,bushu+1);//搜索当前格子
			a[i][y]=1;//回溯
			break;//只搜一遍
		}
		if(a[i][y]==3) {//如果目标点就在当前路径
			minn=bushu+1;//记录答案 步数+1
			break;//停止
		}
	}
	for(int j=x-1; j>=1; j--) {//同上
		if(a[x-1][y]==1)break;
		if(a[j][y]==1) {
			a[j][y]=0;
			dfs(j+1,y,bushu+1);
			a[j][y]=1;
			break;
		}
		if(a[j][y]==3) {
			minn=bushu+1;
			break;
		}
	}
	for(int k=y+1; k<=h; k++) {//同上
		if(a[x][y+1]==1)break;
		if(a[x][k]==1) {
			a[x][k]=0;
			dfs(x,k-1,bushu+1);
			a[x][k]=1;
			break;
		}
		if(a[x][k]==3) {
			minn=bushu+1;
			break;
		}
	}
	for(int l=y-1; l>=1; l--) {//同上
		if(a[x][y-1]==1)break;
		if(a[x][l]==1) {
			a[x][l]=0;
			dfs(x,l+1,bushu+1);
			a[x][l]=1;
			break;
		}
		if(a[x][l]==3) {
			minn=bushu+1;
			break;
		}
	}
}
int main() {
	while(cin>>h>>w) {//输入(坑啊 反着输入)
		minn=11;
		if(w==0&&h==0) {//输入0 0 时停止
			break;
		}
		for(int i=1; i<=w; i++) {
			for(int j=1; j<=h; j++) {
				cin>>a[i][j];
			}
		}
		for(int i=1; i<=w; i++) {
			for(int j=1; j<=h; j++) {
				if(a[i][j]==2) {
					dfs(i,j,0);//从起始点搜索
					break;
				}
			}
		}
		if(minn!=11) cout<<minn<<endl;//最小值改变 输出
		else cout<<-1<<endl;//不能到达 输出-1
	}
	return 0;
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值