题解0008:棋盘游戏

题目链接://ybt.ssoier.cn:8088/problem_show.php?pid=1451

(信奥一本通1451)

题目描述:输入俩棋盘(4*4),一半黑子(1)一半白子(0),两个棋子可以交换,问第一个棋盘要交换多少次才能变成第二个。

题目思路:

广搜,先找出两个棋盘的不同,再两两交换,最后求出步数

但是要是用2维数组模拟的话肯定超时,所以我们要优化一下

我们可以用位运算,将棋盘转成一串2进制数,再转化成10进制存起来

这样就只用判断两个数组了,大大缩短时间

(具体详见代码注释)

#include<bits/stdc++.h>

using namespace std;
struct Q{
	int a,b;
};//存在队列里的结构体,a是二进制状态的当前棋盘,b是步数 
int A,B,arr[1000000]={0};//判断一个位置是否交换过 
void bfs(){
	queue<Q> q;
	q.push((Q){A,0});//将初始棋盘塞入队列,清零步数 
	while(!q.empty()){
		Q u=q.front();
		q.pop();
		int temp=u.a;
		if(temp==B){//如果交换后的棋盘与最终棋盘重合证明找到了,输出结束 
			cout<<u.b;
			return;
		}
		for(int i=15;i>=0;i--){
			int x=(15-i)%4;
			int y=(15-i)/4;
			//找棋盘某位置在数组状态的x和y坐标
			int z=(1<<i); 
			int r;
			if(x<3&&(temp&(1<<i))!=(temp&(1<<i-1))){//判断左右能不能换
               //(x>3是为了不让第一排最后一个和第二排第一个交换) r=(1<<i-1); if(arr[temp^z^r]==0){//判断有没有交换过 arr[temp^z^r]=1; q.push((Q){temp^z^r,u.b+1});//交换棋盘,步数+1 } } if(y<3&&(temp&(1<<i))!=(temp&(1<<i-4))){//判断左右能不能换(上下差4个) r=(1<<i-4); if(arr[temp^z^r]==0){//判断有没有交换过 arr[temp^z^r]=1; q.push((Q){temp^z^r,u.b+1});//交换棋盘,步数+1 } } } } } int main(){ char p;//要一个一个单数存,所以用char int i; for(i=15;i>=0;i--){ cin>>p; A+=(p-'0')*1<<i;//用十进制表示二进制数存棋盘 } for(i=15;i>=0;i--){ cin>>p; B+=(p-'0')*1<<i; } if(A==B){ cout<<"0"; }else{ bfs(); } }

 

Tags: