IDA*比较好,重复路径也无所谓了,A*存状态判重意义不大,不实用
IDA*就是限制搜索深度的dfs,多加了一个limit限制条件,可以得到最优解
八数码的一些解释http://wenku.baidu.com/view/37a1b7a4284ac850ad024269.html
别人的总结http://www.cnblogs.com/JMDWQ/category/383627.html
这篇写的挺简明http://blog.csdn.net/ysjjovo/article/details/6657008
#include<stdio.h>//2 3 4 1 5 x 7 6 8
#include<string.h>
#include<math.h>
#define size 3
int move[4][2]={{-1,0},{0,-1},{0,1},{1,0}};//上 左 右 下
char op[4]={'u','l','r','d'};
int map[size][size],map2[size*size],limit,path[100];
int flag,length;
//int goal_st[3][3]={{1,2,3},{4,5,6},{7,8,0}};
int goal[9][2]={{2,2},{0,0},{0,1},{0,2},{1,0},{1,1},{1,2},{2,0},{2,1}};//目标位置
int nixu(int a[size*size])//算逆序数,逆序数为偶数状态可达
{
int i,j,ni;
ni=0;
for(i=0;i<size*size;i++)
{
if(a[i]==0) //空格不算,只算八个数块的逆序
continue;
for(j=i+1;j<size*size;j++)
{
if(a[j]==0)
continue;
if(a[i]>a[j])
ni++;
}
}
if(ni%2==0)
return 1;
else
return 0;
}
int hv(int a[][size])//估价函数,曼哈顿距离,小等于实际总步数
{
int i,j,cost=0;
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)
{
int w=map[i][j];
cost+=abs(i-goal[w][0])+abs(j-goal[w][1]);
}
}
return cost;
}
void swap(int*a,int*b)
{
int tmp;
tmp=*a;
*a=*b;
*b=tmp;
}
void dfs(int sx,int sy,int len,int pre_move)//sx,sy是空格的位置
{
int i,j,nx,ny;
if(flag)
return;
int dv=hv(map);
if(len==limit)
{
if(dv==0)
{
flag=1;
length=len;
return;
}
else
return;
}
else if(len<limit)
{
if(dv==0)
{
flag=1;
length=len;
return;
}
}
for(i=0;i<4;i++)
{
if(i+pre_move==3&&len>0)//不和上一次移动方向相反,对第二步以后而言
continue;
nx=sx+move[i][0];
ny=sy+move[i][1];
if(0<=nx&&nx<3 && 0<=ny&&ny<3)
{
swap(&map[sx][sy],&map[nx][ny]);
int p=hv(map);
if(p+len<=limit&&!flag)
{
path[len]=i;
dfs(nx,ny,len+1,i);
if(flag)
return;
}
swap(&map[sx][sy],&map[nx][ny]);
}
}
}
int main()
{
int i,j,k,l,m,n,sx,sy;
char c,g;
flag=0;
memset(path,-1,sizeof(path));
i=0;
while(i<9)
{
scanf("%c",&c);
if(c==32)
continue;
if(c=='x')
{
map2[i]=0;
map[i/3][i%3]=0;
sx=i/3;sy=i%3;
i++;
}
else
{
map2[i]=c-48;
map[i/3][i%3]=c-48;
i++;
}
}
if(nixu(map2)==1)//该状态可达
{
limit=hv(map);
limit=0;
while(!flag)//找不到就加大limit,只要状态可达,就总会找到路径,每次搜索的深度都不大于limit,虽然可能错过正确解,但减少了错误路径的搜索长度,总的来说节省了时间
{
dfs(sx,sy,0,0);
if(!flag)
limit++; //得到的是最小步数
}
for(i=0;i<length;i++)
printf("%c",op[path[i]]);
printf("\n");
}
else
printf("unsolvable\n");
return 0;
}
16MS