传送门: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;
}