您的位置:首页 > 其它

八数码问题(hash+bfs)

2017-09-15 20:33 423 查看
小白P131

编号为1~8的8个正方形滑块被摆成3行3列(有一个格子留空)。每次可以把与空格相邻的滑块(有公共边才算相邻)移到空格中,而它原来的位置就成为了新的空格。给定初始局面和目标局面(用0表示空格),你的任务是计算出最少的移动步数。如果无解,输出-1。



#include<stdio.h>
#include<string.h>

const int N=1000000,HN=1000003;
int nx[4][2]={-1,0,1,0,0,-1,0,1};//上下左右

int start
[9],goal[9];//起始数组,目标数组
int first[HN],next
;//链表
int step
;

int hash(int *start)//通过hash函数将每种状态转换成相同长度的整数
{
int ha=0;
for(int i=0;i<9;i++)
ha=ha*10+start[i];//这是一个hash映射函数,通过他可以实现转换
return ha%HN;
}

bool try_insert(int tail)//相当于判断if(book[tx][ty]==0)
{
int ha=hash(start[tail]);
int u=first[ha];
while(u)
{
if(!memcmp(start[u],start[tail],sizeof(start[0]))) return 0;//如果已经走过则返回0
u=next[u];//顺着链表继续找
}
next[tail]=first[ha];
first[ha]=tail;//将这个点插入到链表中
return 1;//没有走过,扩展成功,返回1
}

int bfs()
{
memset(first,0,sizeof(first));
int head=1,tail=2;
while(head<tail)
{
if(memcmp(goal,start[head],sizeof(start[0]))==0) return head;//找到目标状态

int z;//注意将数据带出
for(z=0;z<9;z++)
if(start[head][z]==0) break;//找到"0"
int x=z/3,y=z%3;//转化为坐标形式,x表示行y表示列

for(int i=
d6f6
0;i<4;i++)
{
int tx=x+nx[i][0];
int ty=y+nx[i][1];
int tz=3*tx+ty;//行x列y移动后再转化为下标形式

if(tx>=0&&tx<3&&ty>=0&&ty<3)//总共3行3列
{
memcpy(&start[tail],&start[head],sizeof(start[0]));//将head中的点给tail
start[tail][tz]=start[head][z];
start[tail][z]=start[head][tz];//将0所在的格与旁边的格中的数值交换
step[tail]=step[head]+1;//步数+1
if(try_insert(tail)) tail++;//相当于book,如果这步扩展成功则tail++
}
}
head++;
}
return 0;
}

int main()
{

for(int i=0;i<9;i++)
scanf("%d",&start[1][i]);
for(int i=0;i<9;i++)
scanf("%d",&goal[i]);

int s=bfs();
if(s>0) printf("%d\n",step[s]);
else printf("-1\n");

return 0;
}


#include<stdio.h>
#include<string.h>
#include<algorithm>
#define M 500000
#define Mod 1000003
using namespace std;

int s[9],goal[9],head[Mod],Next[Mod],end,director[M],tt,f;
int nx[4][2]={0,-1,1,0,0,1,-1,0};

struct node
{
int str[9];
int step,first,dir;
}Q[M];

int Hash(int ss[])
{
int sum=0;
for(int i=0;i<9;i++)
sum=sum*10+ss[i];
return sum%Mod;
}

int Try_to_insert(int ss)
{
int h=Hash(Q[ss].str);
int u=head[h];
while(u)
{
if(memcmp(Q[ss].str,Q[u].str,sizeof(goal))==0)
return 0;
u = Next[u];
}
Next[ss]=head[h];
head[h]=ss;
return 1;
}

void find(int x)
{
if(Q[x].dir==-1)
return ;
else
{
find(Q[x].first);
director[tt++]=Q[x].dir;
}
}

void bfs()
{
memcpy(Q[1].str,s,sizeof(s));

int head=1,tail=2;
Q[head].step=0;
Q[head].first=0;
Q[head].dir=-1;

Try_to_insert(1);

while(head<tail)
{

int z;
for(z=0;z<9;z++)
if(!Q[head].str[z]) break;
int y=z/3,x=z%3;

for(int i=0;i<4;i++)
{
int tx=x+nx[i][0];
int ty=y+nx[i][1];
if(tx>=0&&tx<3&&ty>=0&&ty<3)
{
int tz=3*ty+tx;
memcpy(Q[tail].str,Q[head].str,sizeof(goal));

swap(Q[tail].str[z],Q[tail].str[tz]);

if(Try_to_insert(tail))
{
Q[tail].step=Q[head].step+1;
Q[tail].first = head;
Q[tail].dir = i;
if(memcmp(Q[tail].str,goal,sizeof(goal))==0)
{
f=1;
end=tail;
return ;
}
tail++;
}

}
}
head++;
}
}

int main()
{
int i,j,k,t,n;
char ss[1000];
while(gets(ss)!=NULL)
{
int l=strlen(ss);
k=0;
for(i=0;i<l;i++)
{
if(ss[i]>='0'&&ss[i]<='9')
s[k++]=ss[i]-'0';
if(ss[i]=='x')
s[k++]=0;
}
for(i=1;i<=9;i++)
{
if(i==9) goal[i-1]=0;
else goal[i-1]=i;
}

if(memcmp(s,goal,sizeof(s))==0)
{
printf("\n");
continue;
}

memset(head,0,sizeof(head));
end=1;
f=0;
bfs();
tt=0;
if(f)
{
find(end);
for(i=0;i<tt;i++)
{
if(director[i]==0) printf("u");
else if(director[i]==1) printf("r");
else if(director[i]==2) printf("d");
else if(director[i]==3) printf("l");
}
printf("\n");
}
else
printf("unsolvable\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: