您的位置:首页 > 其它

8数码,静态数组+自建开散列哈希表;

2010-06-13 19:31 155 查看
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef int State[9];
const int MAXSTATE=1000000; //状态数不会超过这个,9!种
State st[MAXSTATE],goal; //状态数组, 目标状态
int dist[MAXSTATE]; // 已走步数
int fa[MAXSTATE]; // 前趋状态

/*移动方向*/
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};

//自建hash
const int MAXHASHSIZE=1000003; //比状态数多,是一个奇数,或者是质数
int head[MAXHASHSIZE],next[MAXHASHSIZE];

//初始化哈希表
void initHashTable()
{
memset(head,0,sizeof(head));
}

//哈希函数,随便算,只要别超越int的范围,则可以以表长取余控制在数组范围内
int hash(State &s)
{
int v=0,i;
for(i=0;i<9;++i)
{
v=v*10+s[i];
}
return v%MAXHASHSIZE;
}
//判定插入
int tryToInsert(int s)
{
int h=hash(st[s]);
int u=head[h];
while(u) //从桶内顺序查找是否存在这个状态
{
if(memcmp(st[u],st[s],sizeof(st[s]))==0) //找到状态,说明重复了,就不必插入了
{
return 0;
}
u=next[u];
}
next[s]=head[h];
head[h]=s;
return 1;
}

int bfs()
{
initHashTable(); //初始化状态哈希表为空
int front=1,rear=2; // 数组模拟队列,front队头,rear队尾 ,下标0不适用,作为无解判定,rear下标待存数据
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;
}
}
int x=z/3;
int y=z%3;
for(int d=0;d<4;++d) //以当前状态扩展新状态
{
int newx=x+dx[d];
int newy=y+dy[d];
int newz=newx*3+newy;
if(0<=newx&&newx<3&&0<=newy&&newy<3) //移动没有越界
{
State &t=st[rear];
memcpy(t,s,sizeof(s)); //拷贝一份当前状态
t[newz]=s[z];    //移动
t[z]=s[newz];
dist[rear]=dist[front]+1;  //修改距离
fa[rear]=front;    // 修改前驱
if(tryToInsert(rear)) // 判断状态是否已出现过,出现过就不插入了,会重复运行
++rear;
}
}
++front; //队头元素出队
}
return 0;
}

int main()
{
int i,ans;
for(i=0;i<9;++i)
{
scanf("%d",&st[1][i]);
}
for(i=0;i<9;++i)
{
scanf("%d",&goal[i]);
}
ans=bfs();
if(ans>0)
{
printf("%d/n",dist[ans]);
}
else
{
printf("-1/n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  include 扩展