HDU 1072Nightmare(dfs记忆化搜索+剪枝)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1072

题目大意:伊格内修斯身上的炸弹还有6分钟就要爆炸,他要想办法用最短的时间走出迷宫,0代表一堵墙,表示不可走,1代表没有任何东西,表示可走,2表示起点位置,3表示终点位置,4表示炸弹重置装置。这道题由于有了炸弹重置装置,所以存在着本来无法到达终点,但可以通过迂回策略先前往炸弹重置装置,再前往终点这种可能性。这道题除了可以用dfs写出来,还可以用bfs写出来,不过这里只贴出dfs的代码,bfs的代码下次有时间再贴吧。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=10;
int n,m,vis[maxn][maxn],mp[maxn][maxn],mi,step,Time[maxn][maxn],Len[maxn][maxn];

bool check(int x,int y){//检查是否越界
    if(x>=0&&x<n&&y>=0&&y<m)
    return true;
    return false;
}
void  dfs(int x,int y,int step,int t){
    if(mp[x][y]==3&&t>0){
        if(step<mi){
            mi=step;
        }
        return;
    }
    if(mp[x][y]==4)
    t=6;
    if(step>=Len[x][y]&&Time[x][y]>=t)//剪枝,如果此时不是最优解则返回;
    return;
    Time[x][y]=t;
    Len[x][y]=step;
    int next[4][2]={0,1,1,0,0,-1,-1,0};
    for(int i=0;i<4;i++){//由于存在时间限制,所以允许不对走过的点进行标记
        int nx,ny;
        nx=x+next[i][0];
        ny=y+next[i][1];
        if(check(nx,ny)&&mp[nx][ny]!=0&&t>1){
            dfs(nx,ny,step+1,t-1);
        }
    }
}
int main(){
    int i,j,k,t,sx,sy;
    cin>>t;
    while(t--){
        cin>>n>>m;
        memset(vis,0,sizeof(vis));
        mi=0x3f3f3f3f;step=0;
        memset(Time,-1,sizeof(Time));
        memset(Len,0x3f3f3f,sizeof(Len));
        for(i=0;i<n;i++){
            for(j=0;j<m;j++){
                cin>>mp[i][j];
                if(mp[i][j]==2){
                    sx=i;sy=j;
                }
            }
        }
        dfs(sx,sy,0,6);
        if(mi==0x3f3f3f3f)
        cout<<-1<<endl;
        else 
        cout<<mi<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/k_r_forever/article/details/80504050