给定一个十进制数0≤x<216,将它转换为二进制字符串并在高位填0以补足16位,就得到了一个长度为16的01字符串,我们用这个字符串表示4*4的棋盘,按从左到右,从上到下的顺序将0(白子)、1(黑子)放入棋盘。
我们现在可以交换棋盘中相邻(共享一条边的两个格子相邻,因此一个格子至多有4个相邻的格子)的黑色和白色棋子。从左图的棋盘变为全部白子在上、全部黑子在下(右边棋盘所示)的棋盘,至少需要3步。
对于给定的棋盘(保证棋盘中恰好有8个白子和8个黑子),求把棋盘变为全部白子在上、全部黑子在下最少的交换步数。
输入格式
输入一行一个整数x,为十进制表示下的棋盘。
50%的测试数据满足棋盘可以在6次交换内变为白子在上、黑子在下。所有数据保证0≤x<216,且x转换为二进制后恰好有8个“1”。
输出格式
输出一行一个整数,最少需要交换的步数。
输入/输出例子1
输入:
447
输出:
3
输入/输出例子2
输入:
42405
输出:
8
样例解释
【样例说明1】参考上图,将(2,4)处的黑子移动到(3,3)需要3步
【样例说明2】如图所示,(42405)10=(1010 0101 1010 0101)
● | ○ | ● | ○ |
○ | ● | ○ | ● |
● | ○ | ● | ○ |
○ | ● | ○ | ● |
#include<bits/stdc++.h>
using namespace std;
int a[5][5];
int flag[65536];
int n;
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
struct Node{
int num;
int step;
};
int to_num()
{
int m=0;
for(int i=1;i<=4;i++)
{
for(int j=1;j<=4;j++)
{
m=m*2+a[i][j];
}
}
return m;
}
void to_array(int n)
{
for(int i=4;i>0;i--)
{
for(int j=4;j>0;j--)
{
a[i][j]=n%2;
n/=2;
}
}
}
queue<Node>qu;
int BFS()
{
Node p;
p.num=255;
p.step=0;
if(n==255)
return 0;
qu.push(p);
flag[255]=1;
while(qu.size())
{
p=qu.front();
qu.pop();
int num=p.num;
int s=p.step;
to_array(num);
for(int i=1;i<=4;i++)
{
for(int j=1;j<=4;j++)
{
for(int k=0;k<4;k++)
{
int nx=i+dx[k];
int ny=j+dy[k];
if(nx>=1 && nx<=4 && ny>=1 && ny<=4)
{
swap(a[i][j],a[nx][ny]);
int mm=to_num();
if(mm==n)
return s+1;
if(flag[mm]==0)
{
p.num=mm;
p.step=s+1;
qu.push(p);
flag[mm]=1;
}
swap(a[i][j],a[nx][ny]);
}
}
}
}
}
}
int main(){
cin>>n;
cout<<BFS();
return 0;
}