其他分享
首页 > 其他分享> > 三中的一次普通比赛(六)

三中的一次普通比赛(六)

作者:互联网

题目

三、三中的游戏黑白棋
题目描述
黑白棋游戏的棋盘由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