没有什么特别好的办法,只好用搜索去做
因为一次移动最多归位一个骑士
所以可以想到用IDA*,为了简化状态
我们用k,x,y,sum来表示移动了k步,空格在x,y,还用sum个没有归位的情况
然后枚举转移即可
标准的IDA*
# include<cstring> # include<iostream> # include<cstdio> # include<cmath> # include<cstdio> # include<algorithm> using namespace std; const int mn = 6; int b[mn][mn]={{}, {0,1,1,1,1,1}, {0,0,1,1,1,1}, {0,0,0,-1,1,1}, {0,0,0,0,0,1}, {0,0,0,0,0,0}}; int dx[]={-2,-2,-1,1,-1,1,2,2}; int dy[]={-1,1,2, 2,-2,-2,-1,1}; int a[mn][mn]; int t,sx,sy; int ans=-1; int maxd; bool check(int k,int x,int y,int sum,int la) { if(k+sum>maxd) return false; if(sum==0) return true; bool flag=false; int xx,yy,p,col; for(int i=0;i<=7;i++) { if(i!=7-la) { xx=x+dx[i]; yy=y+dy[i]; p=sum; if(xx>0 && xx<=5 && yy>0 && yy<=5) { if(a[xx][yy]==b[xx][yy] && a[xx][yy]!=b[x][y]) p++; if(a[xx][yy]!=b[xx][yy] && a[xx][yy]==b[x][y]) p--; if(b[xx][yy]==-1) p--; if(b[x][y]==-1) p++; col=a[xx][yy]; a[xx][yy]=-1,a[x][y]=col; flag=check(k+1,xx,yy,p,i); if(flag) return true; a[x][y]=-1,a[xx][yy]=col; } } } return false; } void ida(int ret) { for(maxd=ret;maxd<=16;maxd++)//注意此处要到16 { if(check(0,sx,sy,ret,-1)) { ans=maxd-1; return ; } } } int main() { int ret; char ch; scanf("%d",&t); while(t--) { ans=-1; ret=0; for(int i=1;i<=5;i++) for(int j=1;j<=5;j++) { cin>>ch; if(ch=='*') { a[i][j]=-1; sx=i,sy=j; } else a[i][j]=ch-'0'; if(a[i][j]!=b[i][j]) ret++; } ida(ret); printf("%d\n",ans); } return 0; }