这道题也可以用map来实现,我这里用的是自定义散列函数。因为map是一种普通的实现方式,即是一种通用的实现方式,而对于一个具体的问题,如果你可以用针对这道题的行之有效的方法来解决的话,效率有可能就会高起来。
#include<iostream>
#include<queue>
#include<string>
using namespace std;
#define max 190000
string M[2][max];
queue<string> qu;
string goal="12345678x";
//将二维数组M的值都初始化为x
void init()
{
int i=0;
for(i=0;i<max;i++)
M[0][i]="x";
}
//散列码函数的实现方式
int hashkey(string s)
{
int i;
unsigned int key=0;
for(i=0;i<=8;i++)
{
key=key*13+int(s[i]); //转换为的是字符的ascall码
}
key=key%max;
return key;
}
//通过散列函数找到移动前的状态所对应的下标
int finds(string s)
{
int key=hashkey(s);
int i;
i=key;
while(M[0][i]!=s)
{
i++;
i%=max;
//值为x时表示该下标没有字符串与之对应
if(M[0][i]=="x")
return -1;
}
return i;
}
//冲突处理是通过线性移动来处理的(即向后移动直至找到插入点)
void hashinsert(string s1,string s2)
{
int key=hashkey(s1);
while(M[0][key]!="x"){key++;key%=max;}
M[0][key]=s1;M[1][key]=s2;
}
//借助队列建立散列码和s字符串的对应关系
void Search()
{
string s1=goal,s2;
qu.push(s1);
hashinsert(s1,s1);
int t1,t2;
char temp;
int it;
while(!qu.empty())
{
s1=qu.front();
qu.pop();
for(t1=0;t1<=8;t1++)
if(s1[t1]=='x')
break;
//能往右走
if(t1%3!=2)
{
t2=t1+1;
s2=s1;
temp=s2[t1];s2[t1]=s2[t2];s2[t2]=temp;
it=finds(s2);
if(it==-1)
{
hashinsert(s2,s1);
qu.push(s2);
}
}
if(t1%3!=0)
{
t2=t1-1;
s2=s1;
temp=s2[t1];s2[t1]=s2[t2];s2[t2]=temp;
it=finds(s2);
if(it==-1)
{
hashinsert(s2,s1);
qu.push(s2);
}
}
if(t1/3!=0)
{
t2=t1-3;
s2=s1;
temp=s2[t1];s2[t1]=s2[t2];s2[t2]=temp;
it=finds(s2);
if(it==-1)
{
hashinsert(s2,s1);
qu.push(s2);
}
}
if(t1/3!=2)
{
t2=t1+3;
s2=s1;
temp=s2[t1];s2[t1]=s2[t2];s2[t2]=temp;
it=finds(s2);
if(it==-1)
{
hashinsert(s2,s1);
qu.push(s2);
}
}
}
}
int main()
{
int i;
init(); //将一维数组的值都置为x
Search(); //建立对应关系
string s,s1;
int t1,t2;
char c;
int it;
while(cin>>c)
{
s="";s+=c;
for(i=2;i<=9;i++)
{
cin>>c;
s+=c;
}
it=finds(s); //找到s所在的数组位置
if(it==-1)
cout<<"unsolvable"<<endl;
else
{
while(s!=goal)
{
it=finds(s);
s1=M[1][it]; //s1表示s对应的移动前的状态
for(t1=0;t1<=8;t1++)if(s[t1]=='x')break;
for(t2=0;t2<=8;t2++)if(s1[t2]=='x')break;
t1=t2-t1;
if(t1==3)
cout<<'d';
else if(t1==1)
cout<<'r';
else if(t1==-1)
cout<<'l';
else if(t1==-3)
cout<<'u';
s=s1;
}
cout<<endl;
}
}
return 0;
}
我这里是通过线性扩展来解决位置冲突的。当然还可以用在冲突位置开一条链表的方式来解决。