三中的一次普通比赛(六)
作者:互联网
题目
三、三中的游戏黑白棋
题目描述
黑白棋游戏的棋盘由4×4方格阵列构成。棋盘的每一方格中放有1枚棋子,共有8枚白棋子和8枚黑棋子。这16枚棋子的每一种放置方案都构成一个游戏状态。在棋盘上拥有1条公共边的2个方格称为相邻方格。一个方格最多可有4个相邻方格。在玩黑白棋游戏时,每一步可将任何2个相邻方格中棋子互换位置。对于给定的初始游戏状态和目标游戏状态,编程计算从初始游戏状态变化到目标游戏状态的最短着棋序列。
输入格式
输入文件共有8行。前四行是初始游戏状态,后四行是目标游戏状态。每行4个数分别表示该行放置的棋子颜色。“0”表示白棋;“1”表示黑棋。
输出格式
输出文件的第一行是着棋步数n。接下来n行,每行4个数分别表示该步交换棋子的两个相邻方格的位置。例如,abcd表示将棋盘上(a,b)处的棋子与(c,d)处的棋子换位。输入输出样例
输入样例
1111
0000
1110
0010
1010
0101
1010
0101
输出样例
4
1222
1424
3242
4344
题解
一道bfs状压题
可以利用int的二进制存图
用tomap()和getnum()来进行数图转换
代码
#include<bits/stdc++.h>
using namespace std;
int start,end,sum;
int a[5][5],b[5][5],vis[65540];
int father[65540],f[100000][4];
int dx[4]= {-1,1,0,0};
int dy[4]= {0,0,-1,1};
struct Ans {
int nx,ny,ox,oy,father;
} ans[100000];
queue<int>q;
void read() {
char c;
for(int i=1; i<=4; i++) {
for(int j=1; j<=4; j++) {
cin>>c;
a[i][j]=c-'0';
}
}
for(int i=1; i<=4; i++) {
for(int j=1; j<=4; j++) {
cin>>c;
b[i][j]=c-'0';
}
}
}
int getnum(int a[5][5]) {
int x=0;
for(int i=1; i<=4; i++) {
for(int j=1; j<=4; j++) {
x*=2;
x+=a[i][j];
}
}
return x;
}
void tomap(int x,int a[5][5]) {
while(x) {
for(int i=4; i>=1; i--) {
for(int j=4; j>=1; j--) {
a[i][j]=x%2;
x/=2;
}
}
}
}
bool judge(int ox,int oy,int nx,int ny) {
if(nx>=1&&nx<=4&&ny>=1&&ny<=4&&a[ox][oy]!=a[nx][ny]){
return 1;
}else{
return 0;
}
}
void bfs() {
q.push(start);
vis[start]=1;
while(!q.empty()) {
int exted=q.front();
tomap(exted,a);
q.pop();
for(int i=1; i<=4; i++) {
for(int j=1; j<=4; j++) {
int ox=i,oy=j;
for(int k=0; k<4; k++) {
int nx=ox+dx[k],ny=oy+dy[k];
int flag=0;
if(judge(ox,oy,nx,ny)) { //如果可以交换
flag=1;
int fdeci=getnum(a);
swap(a[ox][oy],a[nx][ny]);
int deci=getnum(a);
if(!vis[deci]) {
vis[deci]=1;
ans[deci].father=fdeci;
ans[deci].nx=nx,ans[deci].ny=ny;
ans[deci].ox=ox,ans[deci].oy=oy;
father[deci]=fdeci;
q.push(deci);
}
if(deci==end)
return;
}
if(flag)
swap(a[ox][oy],a[nx][ny]);
}
}
}
}
}
void work() {
while(father[end]) {
sum++;
f[sum][0]=ans[end].ox;
f[sum][1]=ans[end].oy;
f[sum][2]=ans[end].nx;
f[sum][3]=ans[end].ny;
end=father[end];
}
}
int main() {
read(); //读图
start=getnum(a); //转换a
end=getnum(b); //转换b
bfs();
father[start]=0;
work(); //得到一个输出顺序
cout<<sum<<endl;
for(int i=sum; i>0; i--){
cout<<f[i][0]<<f[i][1]<<f[i][2]<<f[i][3]<<endl;
}
return 0;
}
标签:状态,比赛,int,nx,普通,棋子,三中,方格,游戏 来源: https://blog.csdn.net/dev_cao/article/details/102749570