题目描述 Description
黑白棋游戏的棋盘由4×4方格阵列构成。棋盘的每一方格中放有1枚棋子,共有8枚白棋子和8枚黑棋子。这16枚棋子的每一种放置方案都构成一个游戏状态。在棋盘上拥有1条公共边的2个方格称为相邻方格。一个方格最多可有4个相邻方格。在玩黑白棋游戏时,每一步可将任何2个相邻方格中棋子互换位置。对于给定的初始游戏状态和目标游戏状态,编程计算从初始游戏状态变化到目标游戏状态的最短着棋序列。
输入描述 Input Description
输入共有8行。前四行是初始游戏状态,后四行是目标游戏状态。每行4个数分别表示该行放置的棋子颜色。“0”表示白棋;“1”表示黑棋。
输出描述 Output Description
输出的第一行是着棋步数n。接下来n行,每行4个数分别表示该步交换棋子的两个相邻方格的位置。例如,abcd表示将棋盘上(a,b)处的棋子与(c,d)处的棋子换位。
样例输入 Sample Input
1111
0000
1110
0010
1010
0101
1010
0101
样例输出 Sample Output
4
1222
1424
3242
4344
题解
虽然打着钻石的名号却不过是个暴力,但是这么水的暴力我居然写了那么久!!!!
题目分类是状态压缩,但是我觉得是BFS时的状态压缩,并不是一个DP。16个格子压成2^16不大,才65536,int就够了。然后搜索相邻的不同颜色格子,注意标程应该是枚举格子然后先向下再向右搜的,不这样写会WA2个点。因为可以用65536内的数表示一种状态,先不管输出过程,先打一个找最小步数的BFS,然后用pre[i] 表示i情况的上一步是哪个,step[i] 将从pre[i] —-> i 的转移方式压成一个4位的int存一下,输出时用stack倒个序即可
代码
#include<queue>
#include<stack>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define rep(i) for(int i=1;i<=4;i++)
using namespace std;
const int maxn=100000+10;
const int dx[]={1,0};
const int dy[]={0,1};
struct Node{
int cur,d,pre,step;
Node(int cur,int d,int p,int s):cur(cur),d(d),pre(p),step(s){}
};
int pre[maxn],step[maxn];
int press(int map[5][5])
{
int ret=0;
rep(i) rep(j) ret=ret*2+map[i][j];
return ret;
}
void unpress(int x,int map[5][5])
{
for(int i=4;i>=1;i--)
for(int j=4;j>=1;j--)
{
map[i][j]=x%2;x/=2;
}
return ;
}
int m[5][5],vis[maxn];
bool inside(int x,int y){return x>=1&&x<=4&&y>=1&&y<=4;}
void BFS(int s,int t)
{
queue<Node>q;
q.push(Node(s,0,s,0));
while(!q.empty())
{
Node k=q.front();q.pop();
if(vis[k.cur]) continue;
vis[k.cur]=1;
pre[k.cur]=k.pre;
step[k.cur]=k.step;
if(k.cur==t)
{
stack<int>st;
printf("%d\n",k.d);
for(int i=t;i!=s;i=pre[i])st.push(step[i]);
while(!st.empty()) printf("%d\n",st.top()),st.pop();
return;
}
int tmp[5][5];
unpress(k.cur,tmp);
rep(x) rep(y)
for(int i=0;i<2;i++)
{
int nx=x+dx[i],ny=y+dy[i];
if(inside(nx,ny)&&tmp[nx][ny]!=tmp[x][y])
{
swap(tmp[nx][ny],tmp[x][y]);
int tt=press(tmp);
q.push(Node(tt,k.d+1,k.cur,x*1000+y*100+nx*10+ny));
swap(tmp[nx][ny],tmp[x][y]);
}
}
}
}
int main()
{
rep(i) rep(j) scanf("%01d",&m[i][j]);
int s=press(m);
rep(i) rep(j) scanf("%01d",&m[i][j]);
int t=press(m);
BFS(s,t);
return 0;
}