HRBUST - 2239 - 影子模仿术(bfs)

题目链接:https://vjudge.net/problem/HRBUST-2239

题目大意:和最基础的搜索差不多,只不过在lw移动的同时,pz会向相反方向移动(如果pz可以移动的话)

  很有意思的搜索题,需要注意的是标记访问过的状态的时候要同时标记两个人的位置,因为lw移动的时候pz也可能会移动,这就导致lw在同一个位置的时候,由于先前的操作,pz不一定也在相同的位置,如果只标记lw的位置就有可能少搜索一些情况

#include<set>
#include<map>
#include<list>
#include<stack>
#include<queue>
#include<cmath>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define endl '\n'
#define rtl rt<<1
#define rtr rt<<1|1
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
#define maxx(a, b) (a > b ? a : b)
#define minn(a, b) (a < b ? a : b)
#define zero(a) memset(a, 0, sizeof(a))
#define INF(a) memset(a, 0x3f, sizeof(a))
#define IOS ios::sync_with_stdio(false)
#define _test printf("==================================================\n")
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef pair<ll, ll> P2;
const double pi = acos(-1.0);
const double eps = 1e-7;
const ll MOD =  1000000007LL;
const int INF = 0x3f3f3f3f;
const int _NAN = -0x3f3f3f3f;
const double EULC = 0.5772156649015328;
const int NIL = -1;
template<typename T> void read(T &x){
    x = 0;char ch = getchar();ll f = 1;
    while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
    while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
const int maxn = 30;
int n, m, vis[maxn][maxn][maxn][maxn];
char mp[maxn][maxn];
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int rdir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
struct info {
    int cnt;
    int lx, ly;
    int px, py;
};
inline bool checker(int x1, int y1, int x2, int y2) {
    return (abs(x1-x2) <= 1 && y1==y2) || (abs(y1-y2) <= 1 && x1==x2); 
    //检查pz和lw是否相邻/在同一位置
}
int bfs(int x1, int y1, int x2, int y2) {
    queue<info> qe;
    zero(vis);
    vis[x1][y1][x2][y2] = true;
    info t = {0, x1, y1, x2, y2};
    qe.push(t);
    while(!qe.empty()) {
        t = qe.front(); qe.pop();
        if (checker(t.lx, t.ly, t.px, t.py)) return t.cnt;
        ++t.cnt;
        for (int i = 0; i<4; ++i) {
            int xx = t.lx + dir[i][0], yy = t.ly + dir[i][1];
            if (xx>=0 && xx<n && yy>=0 && yy<m && mp[xx][yy] != 'X') {
                info t2 = {t.cnt, xx, yy, t.px, t.py};
                int xx2 = t2.px + rdir[i][0], yy2 = t2.py + rdir[i][1];
                if (xx2>=0 && xx2<n && yy2>=0 && yy2<m && mp[xx2][yy2] != 'X') {
                    t2.px = xx2, t2.py = yy2;
                    //模拟pz移动
                }
                if (!vis[xx][yy][t2.px][t2.py]) {
                    qe.push(t2);
                    vis[xx][yy][t2.px][t2.py] = true;
                }
            }
        }
    }
    return -1;
}
int main(void) {
    while(~scanf("%d%d", &n, &m)) {
        for (int i = 0; i<n; ++i)
            scanf("%s", mp[i]);
        P t1 = P(-1, -1), t2 = P(-1, -1);
        for (int i = 0; i<n; ++i)
            for (int j = 0; j<m; ++j) {
                if (mp[i][j] == 'L') t1 = P(i, j);
                else if (mp[i][j] == 'P') t2 = P(i, j);
            }
        P t3 = P(-1, -1);
        if (t1 == t3 || t2 == t3) {
            //如果两人在同一个点可能图中只有lw或者pz
            //这时候输出0就是了
            printf("0\n");
            continue;
        }
        int res = bfs(t1.first, t1.second, t2.first, t2.second);
        if (res == -1) printf("Smart PangZi!\n");
        else printf("%d\n", res);
    }
    return 0;
}

 

posted @ 2020-03-13 13:22  shuitiangong  阅读(194)  评论(0编辑  收藏  举报