BZOJ#1054[HAOI2008]移动玩具

[HAOI2008]移动玩具

思路:

把矩阵压缩,然后bfs即可

代码:

#include <bits/stdc++.h>
#define int long long
int _ = 0, Case = 1;
using namespace std;
#define all(v) begin(v),end(v)
#define nline '\n'

const int N = 5;
int get(int x, int y) {
    return x * 4 + y;
}
pair<int, int> moves[] = {{ -1, 0}, {0, -1}, {0, 1}, {1, 0}}; //ULRD
int vis[1 << 16];
struct T {
    int state, step;
};
pair<int, int> get2(int x) {
    return {x / 4, x % 4};
}
char s[N][N], t[N][N];
void solve(int Case) {
    for (int i = 0; i < 4; i++) cin >> s[i];
    for (int i = 0; i < 4; i++) cin >> t[i];
    T start = {0, 0};
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            int k = get(i, j);
            if (s[i][j] == '1') {
                start.state |= (1LL << k);
            }
        }
    }
    int target = 0;
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            int k = get(i, j);
            if (t[i][j] == '1') {
                target |= (1LL << k);
            }
        }
    }
    if (start.state == target) {
        cout << 0 << nline;
        return;
    }
    queue<T> q;
    q.push({start});
    while (q.size()) {
        auto [ns, step] = q.front();
        q.pop();
        for (int i = 0; i < 16; i++) {
            if (ns >> i & 1) {
                auto [x, y] = get2(i);
                for (auto [dx, dy] : moves) {
                    int tx = x + dx, ty = y + dy;
                    int tk = get(tx, ty);
                    if (tx >= 0 and tx<4 and ty >= 0 and ty < 4 and (ns >> tk & 1) == 0) {
                        int news = ns - (1LL << i);
                        news += (1LL << tk);

                        if (!vis[news]) {
                            vis[news] = step + 1;
                            if (news == target) {
                                cout << step + 1 << nline;
                                return;
                            }
                            q.push({news, step + 1});
                        }
                    }
                }
            }
        }
    }
}

signed main() {
    ios::sync_with_stdio(false); cin.tie(nullptr);
//   for (cin>>_, Case = 1; Case <= _; Case++)
    solve(Case);

    return 0;
}
posted @ 2022-06-23 15:53  指引盗寇入太行  阅读(16)  评论(0编辑  收藏  举报