【BZOJ】1085: [SCOI2005]骑士精神-A*搜索

传送门:bzoj1085


题解

A*

状态 x x x估值 f ( x ) = g ( x ) + h ( x ) f(x)=g(x)+h(x) f(x)=g(x)+h(x) g ( x ) g(x) g(x)为已用代价, h ( x ) h(x) h(x)为预计还需花费的最少代价

枚举次数 l i m lim lim搜索,每次只走 f ( x ) ≤ l i m f(x)\leq lim f(x)lim


代码

#include
using namespace std;
const int N=5;

int tk,a[N][N],lim;

const int ans[N][N]=
{
{1,1,1,1,1},
{0,1,1,1,1},
{0,0,2,1,1},
{0,0,0,0,1},
{0,0,0,0,0}
};
const int dx[8]={-1,-2,-2,-1,1,2,2,1};
const int dy[8]={-2,-1,1,2,2,1,-1,-2};
char s[N];

inline int equ()
{
	int i,j,re=0;
	for(i=0;i<N;++i)
	 for(j=0;j<N;++j)
	  if(a[i][j]!=ans[i][j]) re++;
	return re;
}

bool ck(int dep,int x,int y)
{
	if(dep==lim) return equ()==0;
	int i,ix,iy;
	for(i=0;i<8;++i){
		ix=x+dx[i];iy=y+dy[i];
		if(ix<0 || ix>4 || iy<0 || iy>4) continue;
		swap(a[x][y],a[ix][iy]);
		if(equ()+dep<=lim) {if(ck(dep+1,ix,iy)) return true;}
		swap(a[x][y],a[ix][iy]);
	}
	return false;
}

int main(){
	int i,j,x,y;
	for(scanf("%d",&tk);tk;--tk){
		for(i=0;i<N;++i){
		   scanf("%s",s);
		   for(j=0;j<N;++j){
		   	 if(s[j]=='*') {a[i][j]=2;x=i;y=j;}
		   	 else a[i][j]=s[j]-'0';
		   }
		}
		for(lim=0;lim<=15;++lim) if(ck(0,x,y)) {
			printf("%d\n",lim);break;
		}
		if(lim>15) puts("-1");
    }
    return 0;
} 

你可能感兴趣的:(A*算法)