- 八数码问题
- 2017-11-04 15:20:03 @
#include<cstring>
using namespace std;
//八数码:隐式图 归结为图上的最短路
typedef int State[9]; //定义“状态”类型
const int maxstate=1000000;
State st[maxstate],goal={1,2,3,8,0,4,7,6,5}; //状态数组,所有状态都保存在这里
int dist[maxstate]; //距离数组
//如果需要打印方案,可以在这里加一个父亲编号数组int fa[maxstate]
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
//bfs的方向数组
//并看不懂的编码与解码方法
/*int vis[362880],fact[9]; //0-8的排列有9!=362880项
void init_lookup_table(){ //解码与编码:紫书第十章
fact[0]=1;
for(int i=1;i<9;i++) fact[i]=fact[i-1]*1;
}
int try_to_insert(int s){
int code = 0; //把st[s]映射到code
for(int i=0;i<9;i++)
{
int cnt=0;
for(int j=i+1;j<9;j++) if(st[s][j]<st[s][i]) cnt++;
code+=fact[8-i]*cnt;
}
if(vis[code]) return 0;
return vis[code]=1;
}*/
//hash11方法
const int hashsize=1000003;
int head[hashsize],nxt[maxstate];
void init_lookup_table(){memset(head,0,sizeof(head));}
int hash1(State &s){//hash值相同的状态要组成链表
int v=0;
for(int i=0;i<9;i++) v=v*10+s[i];//把九个数字组合成9位数
return v%hashsize;//确保hash函数值是不超过hash表的大小的非负整数
}
int try_to_insert(int s){//插入查找表
int h=hash1(st[s]);
int u=head[h]; //从表头开始查找链表
while(u){
if(memcmp(st[u],st[s],sizeof(st[s])==0) )return 0;//找到了,插入失败
u=nxt[u]; //顺着链表继续找
}
nxt[s]=head[h]; //插入
head[h]=s;
return 1;
}
int bfs(){
init_lookup_table(); //初始化查找表
int front = 1,rear=2;//不用下标0,因为0被看作不存在
while(front<rear){
State &s=st[front]; //用“引用”简化代码
if(memcmp(goal,s,sizeof(s))==0) return front; //找到目标状态,成功返回
int z;
for(z=0;z<9;z++) if(!s[z]) break; //找0的位置,即z的值
int x=z/3,y=z%3; //这步6,找0的坐标
for(int d=0;d<4;d++)
{
int newx=x+dx[d];
int newy=y+dy[d];
int newz=newx*3+newy;//这操作……令人智熄……真的6 要我自己想的话怕是想不到这样表示0的坐标
if(newx>=0&&newx<3&&newy>=0&&newy<3){//如果移动合法
State& t=st[rear]; //rear的状态
memcpy(&t,&s,sizeof(s)); //拓展新结点
t[newz]=s[z];//移动0
t[z]=s[newz];
dist[rear]=dist[front]+1; //更新新结点的距离值
if(try_to_insert(rear)) rear++; //如果成功插入,修改队尾指针
}
}
front++; //拓展完毕后再修改队首指针
}
return 0; //失败
}//memcpy和memcmp 比循环比较和循环赋值要快
int main(){
for(int i=0;i<8;i++){
char c;
c=getchar();
st[1][i]=c-48;
}
char c;
scanf("%c",&c);
st[1][8]=c-48;
int ans=bfs();
if(ans>0) printf("%d\n",dist[ans]);
return 0;
}pp
0 条评论
目前还没有评论...