真的对不住大家。刚刚由于写 代码,一符号搞错了,导致双对列只有一个起作用了。现在该好了。原谅我这个菜鸟呀。
/***
author:zhangrong
date:2013/4/16
title:解决八数码问题
the key of problem:在程序的开始阶段,根据初始化状态与目标状态的奇偶性来判断结果是否存在
因为数字上下左右移动奇偶性不变
//x表示空格
u:上 d:下 l:左 r:右
test: input: 2 3 4 1 5 x 7 6 8
***/
#include<iostream>
#include<string.h>
#include<map>
#define NUM 500000
using namespace std;
struct POINT
{
int s,w;
char d;
}queue[NUM],Fqueue[NUM]; //使用双向队列
char ans[NUM]; //存放答案的数组
int dir[4][2]={1,0,-1,0,0,1,0,-1};//{1,0,0,1,-1,0,0,-1}; //
int main()
{
int t[9]={100000000,10000000,1000000,100000,10000,1000,100,10,1};
int count,m,n,i,j,k;
map<int,int> find; //当find【i】=find[j] 相遇的时候说明有结果了
char w[3][3],w2[9],finaW[9]={'1','2','3','4','5','6','7','8','x'};
//输入初始状态的数组
for(i=0;i<3;i++)
for(j=0;j<3;j++)
cin>>w[i][j];
count=0;
for(i=0;i<3;i++)
for(j=0;j<3;j++)
w2[count++]=w[i][j];
//**************************
//判断是否有解
count=0;
for(i=0;i<9;i++)
for(j=0;j<i;j++)
if(w2[i]!='x'&&w2[j]!='x'&&(w2[i]-'0')<(w2[j]-'0'))
count++;
k=0;
for(i=0;i<9;i++)
for(j=0;j<i;j++)
if(finaW[i]!='x'&&finaW[j]!='x'&&(finaW[i]-'0')<(finaW[j]-'0'))
k++;
if((count%2==k%2))
/*1*/{
int e,s;
int mm,nn,tt,kk,a,b,x,y,g,h,h2; //mm ,nn,记录当前的两队列中的个数,tt,kk表示两队列目前走到哪里,ab表示空格的位置,g.h表示移动时产生的中间变量
s=0;
for(i=0;i<3;i++)
for(j=0;j<3;j++)
{
if(w[i][j]=='x')
s=s*10+9;
else
s=s*10+(w[i][j]-'0');
}
mm=nn=tt=kk=0;
e=123456789;
queue[mm].w=s;
Fqueue[nn].w=e;
find[s]=1; //表示第1个队列的数据
find[e]=2; //表示第2个队列的数据
bool can=false;
if(s==e)
can=true;
while(!can)
/*2*/{
a=0;b=0;
int xx,yy;
for(i=0;i<9;i++) //找出在当前的状态下空格所处的位置
if(queue[tt].w/t[i]%10==9)
{a=i;break;}
for(j=0;j<9;j++)
if(Fqueue[kk].w/t[j]%10==9)
{
b=j;break;
}
//进行广度的遍历
for(i=0;i<4;i++)
/***3**/{
x=a/3;y=a%3;
xx=x+dir[i][0];
yy=y+dir[i][1];
if(xx<3&&yy<3&&xx>=0&&yy>=0&&can==0)
{
s=queue[tt].w;
g=s/t[a];
h2=s/t[xx*3+yy];
g=g%10;
h2=h2%10;
s=s-g*t[a]-h2*t[xx*3+yy];
s=s+h2*t[a]+g*t[xx*3+yy];
if(find[s]!=1)
{
if(find[s]==2)
{
can=1;
}
mm++;
find[s]=1;
queue[mm].w=s;
queue[mm].s=tt;
if(i==0)
queue[mm].d='r';
else if(i==1)
queue[mm].d='l';
else if(i==2)
queue[mm].d='d';
else if(i==3)
queue[mm].d='u';
}
}
//对与反向的队列进行相同的操作
x=b/3;
y=b%3;
xx=x+dir[i][0];
yy=y+dir[i][1];
if(xx>=0&&yy>=0&&xx<3&&yy<3&&can==0)
{
e=Fqueue[kk].w;
g=e/t[b];
h=e/t[xx*3+yy];
g=g%10;
h=h%10;
e=e-g*t[b]-h*t[xx*3+yy];
e=e+g*t[xx*3+yy]+h*t[b];
if(find[e]==0) //由于是相反的方向进行爬取则 记录相反的方向
{
find[e]=2; /*错误的原因***/
nn++;
Fqueue[nn].w=e;
Fqueue[nn].s=kk;
if(i==0)
Fqueue[nn].d='l';
else if(i==1)
Fqueue[nn].d='r';
else if(i==2)
Fqueue[nn].d='u';
else if(i==3)
Fqueue[nn].d='d';
}
}
/***3**/}
tt++;
kk++;
/*2*/}
//输出结果
// cout<<"the final queue is:"<<queue[mm].w<<endl<<"ff"<<Fqueue[nn].w;//为了测试最后的结果是否是最终的目标
i=0;j=mm;
while(j>0)
{
ans[i++]=queue[j].d;
j=queue[j].s;
}
for(int loop=i-1;loop>=0;loop--)
cout<<ans[loop];
i=0;
j=0;
while(Fqueue[j].w!=queue[mm].w)
++j;
while(j>0)
{
ans[i++]=Fqueue[j].d;
j=Fqueue[j].s;
}
for(int lo=0;lo<i;lo++)
cout<<ans[lo];
cout<<endl;
/*1*/}
else
cout<<"My God !No answer\n";
return 0;
}