HDU Tobo or not Tobo IDA*

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;	
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值