Description
传统的我们有8数码问题,即在一个3×3的矩阵中有8个数(1至8)和一个空格,问题要你从一个状态转换到另一个状态,每次只能移动与空格相邻的一个数字到空格当中。
现在给你两个个3*3的矩阵,请给出两个矩阵相互转化的最少步数。
现在给你两个个3*3的矩阵,请给出两个矩阵相互转化的最少步数。
Input
第1行-第3行:3个空格分隔的整数,代表初始状态相应位置的数字,0代表空格
第4行-第6行:3个空格分隔的整数,代表终止状态相应位置的数字,0代表空格
第4行-第6行:3个空格分隔的整数,代表终止状态相应位置的数字,0代表空格
Output
第1行:一个整数,最小转换步数,如不能到相互转化则输出"Impossible"
Sample Input
Original | Transformed |
1 2 3 8 0 4 7 6 5 1 2 3 7 8 4 0 6 5
Sample Output
Original | Transformed |
2
代码如下:
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char a[363000][9]; // 共有9!=362880种情况,用char存储节省空间。
char goal[9];
char visit[363000];
int dis[363000];
int dir[4][2]={{-1,0},{1,0},{0,1},{0,-1}};
int c[9]={1,1,2,6,24,120,720,5040,40320};
// 将字符串转换成一个整数
int find(char str[9])
{
int i,j,k;
int f[10];
int sum = 0;
memset(f,0,sizeof(f));
for(i=0;i<9;i++)
{
k=0;
for(j=0;j<8;j++)
if(j<str[i]&&f[j])
k++;
f[str[i]] = 1;
sum += k*c[8-i];
}
return sum;
}
int bfs()
{
int i,j,t,flag;
int head,tail;
int x,y,z;
int nx,ny,nz;
memset(dis,0,sizeof(dis)); //到每种状态的做小步数
memset(visit,0,sizeof(visit)); //标记过的点不能重复走
t=find(a[0]);
visit[t]=1;
head=0;
tail=1;
while(head<tail)
{
flag=1;
for(i=0;i<9;i++)
if(a[head][i]!=goal[i]) //和目标状态相同即停止搜索
{
flag=0;
break;
}
if(flag)
return dis[head];
for(i=0;i<9;i++) //找到0所在位置
if(a[head][i]==0)
{
x=i/3;
y=i%3;
z=i;
break;
}
for(i=0;i<4;i++)
{
nx=x+dir[i][0];
ny=y+dir[i][1];
nz=nx*3+ny;
if(0<=nx&&nx<3&&0<=ny&&ny<3)
{
for(j=0;j<9;j++)
a[tail][j]=a[head][j];
a[tail][z]=a[head][nz]; //做一次移动,即非0元素和0交换
a[tail][nz]=0;
t=find(a[tail]);
if(!visit[t])
{
visit[t]=1;
dis[tail]=dis[head]+1;
tail++;
}
}
}
head++;
}
return -1;
}
int _tmain(int argc, _TCHAR* argv[])
{
int i,ans;
for(i=0;i<9;i++)
scanf("%d",&a[0][i]);
for(i=0;i<9;i++)
scanf("%d",&goal[i]);
ans = bfs();
if(ans==-1)
printf("Impissible\n");
else
printf("%d\n",ans);
return 0;
}