hdu4528 小明系列故事——捉迷藏(记录状态的BFS)题解

思路:

一道BFS题,和以前的BFS有点不同,这里的vis数组需要记录每次走时的状态,所以开了3维,只对该状态下的vis修改。

注意坑点:S的位置是可以走的

代码:

#include<queue>
#include<cstdio>
#define ll long long
using namespace std;
const int N = 100+5;
char mp[N][N];
bool vis[4][N][N];
int X1,Y1,X2,Y2,x,y,n,m,t,to[4][2] = {0,1,0,-1,1,0,-1,0},cnt = 1;
struct node{
    int x,y;
    int step;
    int Find;
};
void update(node &a){
    if(a.x == X1 && a.Find != 1){   //等于1不改变状态
        int s = min(a.y,Y1) + 1;
        int e = max(a.y,Y1) - 1;
        int flag = 1;
        for(int i = s;i <= e;i++){
            if(mp[X1][i] != '.'){
                flag = 0;
                break;
            }
        }
        if(flag) a.Find = (a.Find == 0? 1 : 3);
    }
    if(a.x == X2 && a.Find != 2){
        int s = min(a.y,Y2) + 1;
        int e = max(a.y,Y2) - 1;
        int flag = 1;
        for(int i = s;i <= e;i++){
            if(mp[X2][i] != '.'){
                flag = 0;
                break;
            }
        }
        if(flag) a.Find = (a.Find == 0? 2 : 3);
    }
    if(a.y == Y1 && a.Find != 1){
        int s = min(a.x,X1) + 1;
        int e = max(a.x,X1) - 1;
        int flag = 1;
        for(int i = s;i <= e;i++){
            if(mp[i][Y1] != '.'){
                flag = 0;
                break;
            }
        }
        if(flag) a.Find = (a.Find == 0? 1 : 3);
    }
    if(a.y == Y2 && a.Find != 2){
        int s = min(a.x,X2) + 1;
        int e = max(a.x,X2) - 1;
        int flag = 1;
        for(int i = s;i <= e;i++){
            if(mp[i][Y2] != '.'){
                flag = 0;
                break;
            }
        }
        if(flag) a.Find = (a.Find == 0? 2 : 3);
    }
}
void BFS(){
    queue<node> q;
    while(!q.empty()) q.pop();
    node a,b;
    a.x = x,a.y = y,a.Find = 0,a.step = 0;
    update(a);
    q.push(a);
    while(!q.empty()){
        a = q.front();q.pop();
        if(a.Find == 3 && a.step <= t){
            printf("Case %d:\n%d\n",cnt++,a.step);
            return;
        }
        for(int i = 0;i < 4;i++){
            b.x = a.x + to[i][0];
            b.y = a.y + to[i][1];
            if(b.x < 1 || b.y < 1 || b.x > n || b.y > m) continue;
            if(mp[b.x][b.y] != '.') continue;
            b.Find = a.Find;
            update(b);
            if(vis[b.Find][b.x][b.y]) continue;
            vis[b.Find][b.x][b.y] = true;
            b.step = a.step + 1;
            q.push(b);
        }
    }
    printf("Case %d:\n-1\n",cnt++);
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d",&n,&m,&t);
        for(int i = 1;i <= n;i++){
            scanf("%s",mp[i] + 1);
            for(int j = 1;j <= m;j++){
                if(mp[i][j] == 'D') X1 = i,Y1 = j;
                else if(mp[i][j] == 'E') X2 = i,Y2 = j;
                else if(mp[i][j] == 'S') x = i,y = j,mp[i][j] = '.';
            }
        }
        memset(vis,0,sizeof(vis));
        BFS();
    }
    return 0;
}


转载于:https://www.cnblogs.com/KirinSB/p/9408796.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值