HDU3085 Nightmare Ⅱ (双向BFS)

联赛前该练什么?DP,树型,状压当然是爆搜啦
双向BFS就是两个普通BFS通过一拼接函数联系,多多判断啦

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define R(a,b,c) for(register int a = (b); a <= (c); ++a)
#define nR(a,b,c) for(register int a = (b); a >= (c); --a)
#define Fill(a,b) memset(a, b, sizeof(a))
#define Swap(a,b) ((a) ^= (b) ^= (a) ^= (b))

#define ON_DEBUGG

#ifdef ON_DEBUGG

#define D_e_Line printf("\n-----------\n")
#define D_e(x) std::cout << (#x) << " : " <<x << "\n"
#define FileOpen() freopen("in.txt", "r", stdin)
#define FileSave() freopen("out.txt", "w", stdout)
#define Pause() system("pause")
#include <ctime>
#define TIME() fprintf(stderr, "\nTIME : %.3lfms\n", clock() * 1000.0 / CLOCKS_PER_SEC)

#else

#define D_e_Line ;
#define D_e(x) ;
#define FileOpen() ;
#define FilSave ;
#define Pause() ;
#define TIME() ;

#endif

struct ios {
    template<typename ATP> ios& operator >> (ATP &x) {
        x = 0; int f = 1; char c;
        for(c = getchar(); c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1;
        while(c >= '0' && c <= '9') x = x * 10 + (c ^ '0'), c = getchar();
        x *= f;
        return *this;
    }
}io;

using namespace std;

template<typename ATP> inline ATP Min(ATP a, ATP b) {
    return a < b ? a : b;
}
template<typename ATP> inline ATP Max(ATP a, ATP b) {
    return a > b ? a : b;
}
#include <queue>

const int N = 1007;

int n, m;
struct Nod {
    int x, y;
};
queue<Nod> q[2];
int step, mx, my, gx, gy, zx[5], zy[5], vis[2][N][N];
int dx[] = {0, 0, -1, 1}, dy[] = {1, -1, 0, 0};
char mp[N][N];
inline bool Check(int x, int y) {
    return (abs(x - zx[1]) + abs(y - zy[1]) > 2 * step) && (abs(x - zx[2]) + abs(y - zy[2]) > 2 * step);
}
inline bool Valid(int x, int y) {
    return x >= 1 && x <= n && y >= 1 && y <= m && mp[x][y] != 'X';
}
inline bool BFS(int t) { // t = 1 -> man, t = 0 -> woman
    int siz = q[t].size();
    while(siz--){
        int x = q[t].front().x, y = q[t].front().y;
        q[t].pop();
        if(!Check(x, y)) continue;
        R(k,0,3){
            int fx = x + dx[k], fy = y + dy[k];
            if(!Valid(fx, fy)) continue;
            if(vis[t][fx][fy]) continue;
            if(!Check(fx, fy)) continue;
            vis[t][fx][fy] = true;
            if(vis[0][fx][fy] && vis[1][fx][fy]) return true;
            q[t].push((Nod){ fx, fy});
        }
    }
    return false;
}

inline int Solve() {
    q[0].push((Nod){ mx, my});
    q[1].push((Nod){ gx, gy});
    step = 0;
    while(!q[0].empty() || !q[1].empty()){
        ++step;
        R(i,1,3){
            if(BFS(0)) return step; // man move three times
        }
        if(BFS(1)) return step; // woman move
    }
    return -1;
}
int main() {
//FileOpen();
    int Tasks;
    io >> Tasks;
    while(Tasks--){
        io >> n >> m;
        R(i,1,n){
            scanf("%s", mp[i] + 1);
        }
        int nmIdx = 0; // night mare
        while(!q[0].empty()) q[0].pop();
        while(!q[1].empty()) q[1].pop();
        Fill(vis, 0);
        R(i,1,n){
            R(j,1,m){
                if(mp[i][j] == 'M'){
                    mx = i, my = j;
                    vis[0][i][j] = true;
                }
                else if(mp[i][j] == 'G'){
                    gx = i, gy = j;
                    vis[1][i][j] = true;
                }
                else if(mp[i][j] == 'Z'){
                    zx[++nmIdx] = i, zy[nmIdx] = j;
                }
            }           
        }
        printf("%d\n", Solve());
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/bingoyes/p/11697022.html