luogu_P1225 黑白棋游戏

https://www.luogu.org/problem/P1225

题目描述

黑白棋游戏的棋盘由4×4方格阵列构成。棋盘的每一方格中放有1枚棋子,共有8枚白棋子和8枚黑棋子。这16枚棋子的每一种放置方案都构成一个游戏状态。在棋盘上拥有1条公共边的2个方格称为相邻方格。一个方格最多可有4个相邻方格。在玩黑白棋游戏时,每一步可将任何2个相邻方格中棋子互换位置。对于给定的初始游戏状态和目标游戏状态,编程计算从初始游戏状态变化到目标游戏状态的最短着棋序列。

输入格式

输入文件共有8行。前四行是初始游戏状态,后四行是目标游戏状态。每行4个数分别表示该行放置的棋子颜色。“0”表示白棋;“1”表示黑棋。

输出格式

输出文件的第一行是着棋步数n。接下来n行,每行4个数分别表示该步交换棋子的两个相邻方格的位置。例如,abcd表示将棋盘上(a,b)处的棋子与(c,d)处的棋子换位。


4*4的矩阵相当于16位的01串,明显用二进制状态压缩,2<<16不超过65535

bfs,矩阵转二进制与二进制转矩阵注意一点

为了输出的答案,需要每个状态记录父状态,转移方法的四位数

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>

#define ri register int
#define u int

using std::string;
using std::cin;
using std::pow;

namespace all {

    u st,ed;

    u q[1000001],fa[65555],n[65555],ans[65555];

    u _a[5][5];

    void dfs(const u &x) {
        if(!fa[x]) {
            return;
        }
        dfs(fa[x]);
        printf("%d
",ans[x]);
    }

    u make() {
        u _re(0);
        for(ri i(1); i<=4; ++i) {
            for(ri j(1); j<=4; ++j) {
                _re=(_re<<1)+_a[i][j];
            }
        }
        return _re;
    }

    void bfs() {
        u l(0),r(0);
        q[++r]=st;
        ans[st]=1;
        while(l+1<=r) {
            u _x(q[++l]);
            if(_x==ed) {
                printf("%d
",n[_x]);
                dfs(_x);
                exit(0);
            }
            u rest(_x);
            for(ri i(1); i<=4; ++i) {
                for(ri j(1); j<=4; ++j) {
                    if(pow(2,(4-i)*4+(4-j))<=rest) {
                        _a[i][j]=1;
                        rest-=pow(2,(4-i)*4+(4-j));
                    } else _a[i][j]=0;
                }
            }
            for(ri i(1); i<=4; ++i) {
                for(ri j(1); j<=4; ++j) {
                    if(i+1<=4) {
                        std::swap(_a[i+1][j],_a[i][j]);
                        u _y(make());
                        if(!ans[_y]) {
                            q[++r]=_y;
                            n[_y]=n[_x]+1;
                            fa[_y]=_x;
                            ans[_y]=i*1000+j*100+(i+1)*10+j;
                        }
                        std::swap(_a[i+1][j],_a[i][j]);
                    }
                    if(j+1<=4) {
                        std::swap(_a[i][j+1],_a[i][j]);
                        u _y(make());
                        if(!ans[_y]) {
                            q[++r]=_y;
                            n[_y]=n[_x]+1;
                            fa[_y]=_x;
                            ans[_y]=i*1000+j*100+i*10+j+1;
                        }
                        std::swap(_a[i][j+1],_a[i][j]);
                    }
                }
            }
        }
    }

    inline void solve() {
        string _s;
        for(ri i(1); i<=4; ++i) {
            cin>>_s;
            for(ri j(0); j<=3; ++j) {
                st=(st<<1)+_s[j]-'0';
            }
        }
        for(ri i(1); i<=4; ++i) {
            cin>>_s;
            for(ri j(0); j<=3; ++j) {
                ed=(ed<<1)+_s[j]-'0';
            }
        }
        bfs();
    }

}

int main() {

    //freopen("x.txt","r",stdin);
    all::solve();

}
原文地址:https://www.cnblogs.com/ling-zhi/p/11732169.html