hdu1401 Solitaire

题目链接: hdu1401 Solitaire

这是一道十分适合双向广搜的题。

考虑到 \(4\) 个相同棋子在一个 \(8\times8\) 的棋盘上,总状态数不过 \(\C_{64}^4=635376<1e6\) 种,单向广搜应该也不会超时,不过我第一次试了下结果还是 \(TLE\) 了,猜想可能是使用 \(map\) 标记耗时的缘故,换成数组标记应该可以过吧。

下面是双向 \(BFS\)\(AC\) 代码。

/**
* hdu1401 Solitaire
*
*/

#include <cstdio>
#include <queue>
#include <iostream>
#include <cstring>
#include <string>
#include <stack>
#include <vector>
#include <map>
#include <cstdlib>
#include <algorithm>
using namespace std;

int id(int *num)
{
    int tmp[4];
    for (int i = 0; i < 4; ++i) {
        tmp[i] = num[2*i]*10+num[2*i+1];
    }
    sort(tmp, tmp+4);
    int res = 0;
    for (int i = 0; i < 4; ++i) res = res*100+tmp[i];
// for (int i = 0; i < 4; ++i) cout << tmp[i] << ' '; cout << endl;
    return res;
}
int sid, eid;

struct node{int x, step;};
int dir[4][2] = {-1,0,1,0,0,-1,0,1}; // 上下左右
map<int, int> vis;
int bfs()
{
    queue<node> Q;
    Q.push(node{sid, 0});
    vis[sid] = 1;
    while (!Q.empty()) {
        node t = Q.front(); Q.pop();
        // cout << t.x << '#';
        if (t.x == eid) return 1;
        if (t.step == 4) continue;  // 步数大于4的就不用入队了
        int num[] = {t.x/1000000,t.x/10000%100,t.x/100%100,t.x%100};
        for (int i = 0; i < 4; ++i) {  // 分别处理4个piece
// cout << num[i] << ':' << endl;
            int x = num[i]/10, y = num[i]%10;
            for (int j = 0; j < 4; ++j) { // 遍历四个方向
                int tx = x+dir[j][0];
                int ty = y+dir[j][1];  // 这里开始不小心写成 ty=x+dir[j][1]
                                       // 果然菜是有原因的
                if (tx < 1 || tx > 8) continue;
                if (ty < 1 || ty > 8) continue;
                int n = tx*10+ty;
                for (int k = 0; k < 4; ++k) if (n == num[k]) {  // 有冲突则再移一格,相当于jump
                    tx += dir[j][0];
                    ty += dir[j][1];
                    break;
                }
                if (tx < 1 || tx > 8) continue;
                if (ty < 1 || ty > 8) continue;
                n = tx*10+ty;
                if (n == num[0]) continue;
                if (n == num[1]) continue;
                if (n == num[2]) continue;
                if (n == num[3]) continue;
                int tmp[8];
                for (int k = 0; k < 4; ++k) {
                    tmp[2*k] = num[k]/10;
                    tmp[2*k+1] = num[k]%10;
                }
                tmp[2*i] = tx, tmp[2*i+1] = ty;
                int nid = id(tmp);
                if (vis[nid]) continue;
                Q.push(node{nid, t.step+1});
                vis[nid] = 1;
            }
// cout << endl;
        }
// system("pause");
    }
    return 0;
}

int bfs2()
{
    queue<node> Q;
    Q.push(node{eid, 0});
    vis[eid] = 2;
    while (!Q.empty()) {
        node t = Q.front(); Q.pop();
        if (t.step == 4) continue;  // 步数大于4的就不用入队了
        int num[] = {t.x/1000000,t.x/10000%100,t.x/100%100,t.x%100};
        for (int i = 0; i < 4; ++i) {  // 分别处理4个piece
            int x = num[i]/10, y = num[i]%10;
            for (int j = 0; j < 4; ++j) { // 遍历四个方向
                int tx = x+dir[j][0];
                int ty = y+dir[j][1];
                if (tx < 1 || tx > 8) continue;
                if (ty < 1 || ty > 8) continue;
                int n = tx*10+ty;
                for (int k = 0; k < 4; ++k) if (n == num[k]) {  // 有冲突则再移一格,相当于jump
                    tx += dir[j][0];
                    ty += dir[j][1];
                    break;
                }
                if (tx < 1 || tx > 8) continue;
                if (ty < 1 || ty > 8) continue;
                n = tx*10+ty;
                if (n == num[0]) continue;
                if (n == num[1]) continue;
                if (n == num[2]) continue;
                if (n == num[3]) continue;
                int tmp[8];
                for (int k = 0; k < 4; ++k) {
                    tmp[2*k] = num[k]/10;
                    tmp[2*k+1] = num[k]%10;
                }
                tmp[2*i] = tx, tmp[2*i+1] = ty;
                int nid = id(tmp);
                int tv = vis[nid];
                if (tv == 2) continue;
                else if (tv == 1) return 1;
                Q.push(node{nid, t.step+1});
                vis[nid] = 2;
            }
        }
    }
    return 0;
}

int main()
{
    int s[8], e[8];
    while (cin >> s[0]) {
        for (int i = 1; i < 8; ++i) cin >> s[i];
        for (int i = 0; i < 8; ++i) cin >> e[i];
        sid = id(s), eid = id(e);
        // cout << sid << ' ' << eid << endl;

        vis.clear();
        if (bfs()) puts("YES");
        else puts(bfs2()?"YES":"NO");
    }
    return 0;
}

posted @ 2021-01-24 16:36  Zewbie  阅读(92)  评论(0)    收藏  举报