1. 程式人生 > >hdu 1072 Nightmare(BFS)

hdu 1072 Nightmare(BFS)

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=1072

題目大意:逃出迷宮,有6秒的時間限制,但是可以通過到達4點來重置時間回到6秒,求最短時間。不能逃出輸出-1.

題目思路:算最短時間,用寬度優先搜尋,由於4點可以重複到達,因此不能直接標記所有走過的點。但是重複到達4點是沒有意義的,所以每個位置的4點最多經過1次,走過之後把它標記為牆就行了,不然會超記憶體。

AC程式碼:

#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
const int MAXN = 12;
int mp[MAXN][MAXN];
int vis[MAXN][MAXN][MAXN];
int d[MAXN][MAXN];
struct node{
    int x,y,t,dis;
};
queue<node> q;
int sx,sy,ex,ey;
int n,m;

int C(int x,int y,int t){
    if(x>=0 && x<n && y>=0 &&y<m && mp[x][y]!=0 && !vis[x][y][t])
        return 1;
    return 0;
}

int solve(){
    memset(d,0,sizeof(d));
    memset(vis,0,sizeof(vis));
    while(!q.empty()) q.pop();
    q.push((node){sx,sy,6,0});
    while(!q.empty()){
        node now=q.front();q.pop();
        vis[now.x][now.y][now.t]=1;
        for(int i=0;i<4;i++){
            int dx=now.x+dir[i][0];
            int dy=now.y+dir[i][1];
            int tmp=now.t-1;
            if(C(dx,dy,tmp)&& tmp>0){
                d[dx][dy]=d[now.x][now.y]+1;
                if(mp[dx][dy]==1 && tmp>0){
                    q.push((node){dx,dy,tmp,d[dx][dy]});
                }else if(mp[dx][dy]==3 && tmp>0){
                    return d[dx][dy];
                }else if(mp[dx][dy]==4 && tmp>0){
                    q.push((node){dx,dy,6,d[dx][dy]});
                    mp[dx][dy]=0;
                }
            }
        }
    }
    return -1;
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                scanf("%d",&mp[i][j]);
                if(mp[i][j]==2){
                    sx=i;
                    sy=j;
                }
            }
        }
        printf("%d\n",solve());
    }
    return 0;
}