迷宫问题-求最短时间

士兵在迷宫中执行任务,迷言中危机重重,他需要在在最短的时问内到达指定的位置。你可以告诉士兵他最少需要多长时问吗?
输入一个n*m的迷宫中,迷宫中0为路,1为墙,2为起点,3为终点,4为陷阱,6为炸弹。士兵只能向上下左右四个方向移动,如果路径上为墙,不能移动。已知每走一步需要花费1个单位的时间,走到陷阱上需要花费3个单位的时间,走到x弹上将会激活炸弹将炸弹上下右的墙炸为路。
注意点:
1、炸弹只能炸毁墙,不会炸掉陷阱
2、炸弹、陷阱只能发挥1次作用
3、迷宫为最大为25*25
4、用例保证士兵定有方法能到达终点

输入:
第一行输入:n和m
第二行输入:n*m的矩阵

输出
最少需要的单位时间

  • 样例
    输入:44
    1 1 1 1
    1 6 2 1
    1 1 0 1
    1 3 1 1
    输出:3
    解释:士兵在位置2,向左移动到炸弹上,会将炸弹周围的墙炸掉,向下走两步即可到达终点

分析:
需要求出最短的时间,所以需要计算出所用能到达终点的结果,取最小的值,因此可以使用回溯
递归时需要判断四个方向的四个点是否能走,如果能走就加入到队列,然后出队的时候注意回溯问题
同时根据迷宫节点类型加上其相应的时间。

代码如下:

#include<iostream>
#include<queue>

using namespace std;
int set_time(int time,bool is) {
	if(is){ //陷阱
		time += 3;
	} else {
		time -=3;
	}
	return time;
    
}

int pos[4][2]={-1,0,1,0,0,-1,0,1};	//可以走的位置
int ans;
int mg[25][25];
int n,m;
void findWay(int x,int y,int time)
{
	if(mg[x][y]==3){ //终点
		ans=time<ans?time:ans;
		return;
	}

    if(mg[x][y]==6) { //炸弹
        if(x>1 &&mg[x-1][y]==1) mg[x-1][y] = 0;
        if(x<=n&&mg[x+1][y]==1)mg[x+1][y] = 0;
        if(y<=m&&mg[x][y+1]==1)mg[x][y+1] =0;
        if(y>1&&mg[x][y-1]==1)mg[x][y-1] = 0;
    }
	queue<int> point;
	for(int i=0;i<4;i++){
		//&&mg[x+pos[i][0]][y+pos[i][1]]!=3
		if(x+pos[i][0]>0&&x+pos[i][0]<=n&&y+pos[i][1]<=m&&y+pos[i][1]>0&&mg[x+pos[i][0]][y+pos[i][1]]!=1){ // 可以走并且不是终点
			point.push(x+pos[i][0]);
			point.push(y+pos[i][1]);
		}
	}
	int nx,ny;
	int hs;
	bool is = true;
	while(!point.empty()){
		nx=point.front();
		point.pop();
		ny=point.front();
		point.pop();
		hs = mg[x][y];
		mg[x][y]=1;
		if(mg[nx][ny] == 4) {
			time = set_time(time,is);
			is = false;
		} else time++;
		findWay(nx,ny,time);
		mg[x][y]=hs;
		if(!is) time = set_time(time,is);
		else time--;
	}
}

int main() {
    int bx,by; //起点
    while(cin>>n>>m)
    {
    	ans=n*m*9;
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=m;j++){
    			cin>>mg[i][j];
    			if(mg[i][j]==2){
    				bx=i;
    				by=j;
				}
			}
		}
		findWay(bx,by,0);
		if(ans==n*m*9){
			cout<<"unable"<<endl;
		}else{
			cout<<ans<<endl;
		}
	}
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cali321

您一定能解决问题的

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值