http://acm.hdu.edu.cn/showproblem.php?pid=1813
题意: 给一个3x3的矩阵,问是否能在规定的步数之内还原回原来的样子,若能输出最少的步数,若不能输出-1.
算法: IDA*。相对于A*算法来说,IDA*的空间需求少是其的优势。 IDA*的关键就是要选好h()函数,本题用曼哈顿距离作为其h函数的值。
代码:
/*
HDU 2918 Tobo or not Tobo
Tips : IDA*搜索。
runtime : 0ms
Memory 180K
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int maze[4][4] ;
int max_deep,deep;
int dr[10] = {1,1,1,1,2,2,2,3,3,3} ;
int dc[10] = {1,1,2,3,1,2,3,1,2,3} ;
char ch[15];
inline void inti()
{
int num=1;
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
maze[i][j] = ch[num++] - '0' ;
}
}
max_deep = ch[0] - '0' ;
}
//曼哈顿距离
int get_h(){
int res = 0 ;
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
res = res + abs(dr[maze[i][j]]-i)+abs(dc[maze[i][j]]-j) ;
//printf("%d %d %d %d %d %d\n",maze[i][j],dr[maze[i][j]],dc[maze[i][j]],i,j,res);
}
}
return res ;
}
/*
一开始的一个h函数,效果不是很好,runtime:158ms
int get_h(){
int res = 0 ;
for(int i=1;i<=3;i++){
int start = (i-1)*3 + 1;
int end = i * 3 ;
for(int j=1;j<=3;j++){
if(maze[i][j]<start || maze[i][j]>end)
res ++ ;
}
}
return res ;
}
*/
bool is_ok(){
int num = 1 ;
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
if(maze[i][j] != num) return false ;
num ++ ;
}
}
return true ;
}
void A_LR(){
int temp = maze[1][1];
maze[1][1] = maze[1][2] ;
maze[1][2] = maze[2][2] ;
maze[2][2] = maze[2][1] ;
maze[2][1] = temp ;
}
void A_RR(){
int temp = maze[1][1] ;
maze[1][1] = maze[2][1] ;
maze[2][1] = maze[2][2] ;
maze[2][2] = maze[1][2] ;
maze[1][2] = temp ;
}
void B_LR(){
int temp = maze[1][2] ;
maze[1][2] = maze[1][3] ;
maze[1][3] = maze[2][3] ;
maze[2][3] = maze[2][2] ;
maze[2][2] = temp ;
}
void B_RR(){
int temp = maze[1][2] ;
maze[1][2] = maze[2][2] ;
maze[2][2] = maze[2][3] ;
maze[2][3] = maze[1][3] ;
maze[1][3] = temp ;
}
void C_LR(){
int temp = maze[2][1] ;
maze[2][1] = maze[2][2] ;
maze[2][2] = maze[3][2] ;
maze[3][2] = maze[3][1] ;
maze[3][1] = temp ;
}
void C_RR(){
int temp = maze[2][1] ;
maze[2][1] = maze[3][1] ;
maze[3][1] = maze[3][2] ;
maze[3][2] = maze[2][2] ;
maze[2][2] = temp ;
}
void D_LR(){
int temp = maze[2][2] ;
maze[2][2] = maze[2][3] ;
maze[2][3] = maze[3][3] ;
maze[3][3] = maze[3][2] ;
maze[3][2] = temp ;
}
void D_RR(){
int temp = maze[2][2] ;
maze[2][2] = maze[3][2] ;
maze[3][2] = maze[3][3] ;
maze[3][3] = maze[2][3] ;
maze[2][3] = temp ;
}
bool dfs(int d){
if(is_ok() && d==deep) return true ;
int h = get_h();
if(d+(h+3)/4 > deep) return false ;
A_LR();if(dfs(d+1)) return true ;A_RR();
A_RR();if(dfs(d+1)) return true ;A_LR();
B_LR();if(dfs(d+1)) return true ;B_RR();
B_RR();if(dfs(d+1)) return true ;B_LR();
C_LR();if(dfs(d+1)) return true ;C_RR();
C_RR();if(dfs(d+1)) return true ;C_LR();
D_LR();if(dfs(d+1)) return true ;D_RR();
D_RR();if(dfs(d+1)) return true ;D_LR();
return false ;
}
int main()
{
int ncase = 1 ;
while(scanf("%s",ch)){
if(strcmp(ch,"0000000000")==0) break;
inti();
deep = 0 ;
while(deep <= max_deep){
if(dfs(0)) break ;
deep++ ;
}
if(deep > max_deep)
printf("%d. -1\n",ncase++);
else
printf("%d. %d\n",ncase++,deep);
}
return 0;
}