士兵在迷宫中执行任务,迷言中危机重重,他需要在在最短的时问内到达指定的位置。你可以告诉士兵他最少需要多长时问吗?
输入一个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;
}