题解0008:棋盘游戏

题目链接:http://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(); } }

 

posted @ 2022-04-10 22:02  uf0_金币灰黄^w.h  阅读(203)  评论(0)    收藏  举报