分析:经典的八数码问题,参考别人的代码写的,逆向广搜,把结果保存起来,之后在使用。
#include<iostream>
#include<queue>
using namespace std;
#define STATE_COUNT 363000 //因为9!=362880
int fact[]={1,1,2,6,24,120,720,5040,40320,362880}; //0到9的阶乘,用来计算hash值
char dir[4][2]={
{0,1},{0,-1},{1,0},{-1,0} //右,左,上,下
};
char dirchar[]="lrud"; //因为是从合法状态搜索出其他状态,方便之后返回时好处理,所以和搜索方向相反
class Eight_Puzzle
{
private:
struct Node
{
char map[3][3];
char x_pos_x,x_pos_y;
void GetMap(char* p);
};
public:
Eight_Puzzle(){}
~Eight_Puzzle(){}
void Bfs(); //广度搜索打表
void OutPut(char* p); //根据状态输出结果
private:
void OutPut(int hash);
int Get_Hash(Node p); //获取某个状态的hash值
char m_path[STATE_COUNT];
bool m_vis[STATE_COUNT];
int m_pre[STATE_COUNT];
queue<Node> m_q; //搜索队列
};
void Eight_Puzzle::OutPut(int hash)
{
if(hash<=0) return ;
printf("%c",m_path[hash]);
OutPut(m_pre[hash]);
}
void Eight_Puzzle::OutPut(char* p)
{
Node tmp;
int hash;
tmp.GetMap(p);
hash=Get_Hash(tmp);
if(!m_vis[hash]) //表中无该hash值,说明状态不可达
{
printf("unsolvable\n");
return ;
}
else if(hash==0) //标准状态,无需移动
{
printf("\n");
return ;
}
else
{
OutPut(hash);
printf("\n");
}
}
void Eight_Puzzle::Bfs()
{
char start[]="12345678x";
Node tmp;
int i,x,y;
int hash0,hash;
memset(m_path,0,sizeof(m_path));
memset(m_vis,0,sizeof(m_vis));
memset(m_pre,0,sizeof(m_pre));
m_vis[0]=true; //起点设置为拜访
tmp.GetMap(start);
m_q.push(tmp); //起始状态入队
while(!m_q.empty())
{
tmp=m_q.front();
hash0=Get_Hash(tmp); //队头的hash,当前步
for(i=0;i<4;i++)
{
tmp=m_q.front(); //每次都重新取出队头
x=tmp.x_pos_x+dir[i][0];
y=tmp.x_pos_y+dir[i][1];
if(x<0 || y<0 || x>=3 || y>=3)
continue;
swap(tmp.map[tmp.x_pos_x][tmp.x_pos_y],tmp.map[x][y]);
tmp.x_pos_x=x; //更新坐标
tmp.x_pos_y=y;
hash=Get_Hash(tmp);
if(m_vis[hash])
continue;
m_vis[hash]=true;
m_pre[hash]=hash0;
m_path[hash]=dirchar[i];
m_q.push(tmp);
}
m_q.pop(); //队头出队,状态已处理
}
}
int Eight_Puzzle::Get_Hash(Node p)
{
char s[10];
int i,j,k,count;
int hash=0;
for(i=0;i<3;i++)
for(j=0;j<3;j++)
{
count=0;
s[i*3+j]=p.map[i][j];
for(k=i*3+j-1;k>=0;k--)
if(s[k]>s[i*3+j])
count++;
hash+=count*fact[i*3+j];
}
return hash;
}
void Eight_Puzzle::Node::GetMap(char* p)
{
int i,j;
i=j=0;
while(*p)
{
if(*p>='1' && *p<='8' || *p=='x')
{
map[i][j]=*p;
if(map[i][j]=='x')
{
map[i][j]='9';
x_pos_x=i;
x_pos_y=j;
}
j++;
if(j>=3)
{
i++;
j=0;
}
}
p++;
}
}
int main()
{
char a[50];
Eight_Puzzle* eight_puzzle=(Eight_Puzzle*)new Eight_Puzzle;
eight_puzzle->Bfs(); //打表,保存所有合法移动的步骤
while(gets(a))
{
eight_puzzle->OutPut(a);
}
delete eight_puzzle;
return 0;
}HDU ACM 1043 Eight->广度优先搜索(BFS)+康托展开(全排列hash)实践
原文地址:http://blog.csdn.net/a809146548/article/details/45315021