經典的八數碼問題,用單向BFS,雙向BFS,A*均可解決!
難點在於狀態壓縮,用9代表x,那麼這個矩形的數字擺放狀態共有9!種。9!並不大,可以開一個數組標記狀態,那麼如何將一個數字擺放狀態轉換爲一個整型的十進制數變成了解決問題的關鍵!
參考康託展開:http://blog.csdn.net/morgan_xww/article/details/6275460;
解決了狀態表示問題,下面的編碼就簡單了。
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define MAX 362890
typedef struct node
{
int v;
int x,y;
}node;
node queue[MAX*10];
int flag[MAX]; //狀態標記數組,並記錄上一個狀態裝換成當前狀態所移動的方向,1-u ,2-d,3-l,4-r;-1代表沒訪問過
int map[10],m;
int d[]={1,1,2,6,24,120,720,5040,40320};
char cc[]="udlr";
int count() //康託展開
{
int i,j;
int sum=0;
for (i=0;i<9;i++)
{
//printf("%d ",map[i]);
int tot=0;
for (j=i+1;j<9;j++)
{
if (map[i]>map[j])
tot++;
}
sum+=tot*d[8-i];
}
//printf("\n");
return sum;
}
void swap(int x,int y)
{
int temp=map[x];
map[x]=map[y];
map[y]=temp;
}
void incount(int sum) //康託展開逆運算
{
int i,j,t,vs[10]={0};
for (i=0;i<9;i++)
{
t=sum/d[8-i];
for (j=1;j<=9;j++)
{
if (!vs[j])
{
if (t==0)
break;
else
t--;
}
}
map[i]=j;
vs[j]=1;
sum=sum%d[8-i];
}
}
void bfs()
{
int qs,qe;
qs=qe=0;
queue[0].x=-1;
int tot=count();
queue[0].y=m;
queue[qe++].v=tot;
flag[tot]=0;
while (qs<qe)
{
node temp=queue[qs++];
incount(temp.v);
//printf("%d %d %d\n",temp.x,temp.y,temp.v);
///system("pause");
if (temp.v==0)
break;
if (temp.y-3>=0)
{
swap(temp.y,temp.y-3);
tot=count();
//printf("%d\n",tot);
if (flag[tot]==-1)
{
queue[qe].v=tot;
queue[qe].x=qs-1;
queue[qe++].y=temp.y-3;
flag[tot]=1;
}
swap(temp.y,temp.y-3);
}
if (temp.y+3<9)
{
swap(temp.y,temp.y+3);
tot=count();
//printf("%d\n",tot);
if (flag[tot]==-1)
{
queue[qe].v=tot;
queue[qe].x=qs-1;
queue[qe++].y=temp.y+3;
flag[tot]=2;
}
swap(temp.y,temp.y+3);
//system("pause");
}
if (temp.y%3!=0)
{
swap(temp.y,temp.y-1);
tot=count();
//printf("%d\n",tot);
if (flag[tot]==-1)
{
queue[qe].v=tot;
queue[qe].x=qs-1;
queue[qe++].y=temp.y-1;
flag[tot]=3;
}
swap(temp.y,temp.y-1);
}
if (temp.y%3!=2)
{
swap(temp.y,temp.y+1);
tot=count();
//printf("%d\n",tot);
if (flag[tot]==-1)
{
queue[qe].v=tot;
queue[qe].x=qs-1;
queue[qe++].y=temp.y+1;
flag[tot]=4;
}
swap(temp.y,temp.y+1);
}
//printf("%d\n",qe);
//printf("\n");
//count();
//printf("\n");
}
if (flag[0]==-1)
{
printf("unsolvable\n");
}
else
{
int x=qs-1,top=0;
//queue[top++].v=flag[queue[x].v];
while (queue[x].x!=-1)
{
queue[top++].y=flag[queue[x].v];
x=queue[x].x;
}
for (int i=top-1;i>=0;i--)
{
//printf("%d\n",queue[i].v-1);
printf("%c",cc[queue[i].y-1]);
}
printf("\n");
}
}
int main()
{
char s[20];
while (gets(s))
{
int i,j=0,n;
n=strlen(s);
memset(flag,-1,sizeof(flag));
for (i=0;i<n;i++)
{
if (s[i]>='0'&&s[i]<='9')
{
map[j++]=s[i]-'0';
}
else if (s[i]>='a'&&s[i]<='z')
{
map[j++]=9;
m=j-1;
}
}
/*for (i=0;i<9;i++)
{
printf("%d ",map[i]);
}
printf("\n");*/
bfs();
}
return 0;
}