六数码问题

来源:互联网 发布:千牛怎么没有mac版 编辑:程序博客网 时间:2024/05/14 06:26

描述:

现有一两行三列的表格如下:

A B C
D E F

把1、2、3、4、5、6六个数字分别填入A、B、C、D、E、F格子中,每个格子一个数字且各不相同。每种不同的填法称为一种布局。如下:

1 3 5
2 4 6
布局1

2 5 6
4 3 1
布局2

定义α变换如下:把A格中的数字放入B格,把B格中的数字放入E格,把E格中的数字放入D格,把D格中的数字放入A格。
定义β变换如下:把B格中的数字放入C格,把C格中的数字放入F格,把F格中的数字放入E格,把E格中的数字放入B格。

问:对于给定的布局,可否通过有限次的α变换和β变换变成下面的目标布局:

1 2 3
4 5 6
目标布局

输入:

本题有多个测例,每行一个,以EOF为输入结束标志。每个测例的输入是1到6这六个数字的一个排列,空格隔开,表示初始布局ABCDEF格中依次填入的数字。

输出:

每个输出占一行。可以转换的,打印Yes;不可以转换的,打印No。

输入样例:

1 3 5 2 4 62 5 6 4 3 1

输出样例:

NoYes



#include<iostream>
#include<stdio.h>
#include<queue>
using namespace std;


queue<int>q1;
int used[666666]={0},b[10]={0};
int sm[2][3],am[2][3];
int isdata;


void readdata();
void init();
int bfs();
int moveto(int u,int i);




int main()
{
int i,j;
int num=0;
while(scanf("%d",&sm[0][0])!=EOF)
{
//初始化。 
while(!q1.empty())
{
q1.pop();
}
for(i=0; i<666666; i++)
{
used[i]=0;
}
for(i=0; i<2; i++)
{
for(j=0; j<3; j++)
{
am[i][j]=0;
}


for(i=0; i<2; i++)
{
for(j=0; j<3; j++)
{
//sm[0][0]前面已经输过了。 
if(i==1||(i==0&&j!=0))
{
cin>>sm[i][j];
}
}
}

readdata();

init();

num=bfs();
if(num==1)
{
cout<<"Yes"<<endl;
}
else
{
cout<<"No"<<endl;
}
}


return 0;
}


int bfs()
{
int u,v,i;
while(!q1.empty())
{
u=q1.front();
q1.pop();
for(i=0; i<2; i++) //i=0表示a变换i=1表示β变换 
{
v=moveto(u,i);//v为变化后的状态。 
if(v==123456) //若为目标状态。 
{
return 1;
}
if(used[v]==0)// 如果状态没有出现过就放入队列。 
{
q1.push(v);
used[v]=1;
}
}

return 0;
}




void readdata()
{
isdata=0;
int i,j;
for(i=0; i<2; i++)
{
for(j=0; j<3; j++)
{
isdata=isdata*10+sm[i][j];//使读入的数据变成一个六位数 

}
}


void init()
{
q1.push(isdata);//放入队列。 
used[isdata]=1;//用来判重并记录步数。 





int moveto(int u,int tmp)
{
int v=0,a[6];
int i,j,num=0;
int t=0,m=0;
//先让u变化数组。 
for(i=1; i>=0; i--)
{
for(j=2; j>=0; j--)
{
sm[i][j]=u%10;
u=u/10;
}
}

for(i=0; i<2; i++)
{
for(j=0; j<3; j++)
{
a[num]=sm[i][j];
num++;
}
}
//进行变化。 
if(tmp==0)
{
v=a[0]*10000+a[1]*10+a[2]*1000+a[3]*100000+a[4]*100+a[5];
return v;
}
if(tmp==1)
{
v=a[0]*100000+a[1]*1000+a[2]+a[3]*100+a[4]*10000+a[5]*10;
return v;
}

}