【传送门:BZOJ1085】
简要题意:
有一个5*5的棋盘,棋盘上有12个白棋子,12个黑棋子,和一个空格,每只棋子只能按照马走日的规则移动,求出最少步数达到以下状态
题解:
DFS+A*
DFS很容易做,不过时间复杂度太高
所以用A*来优化时间
A*的好处预判当前递归到结束得到的值,从而判断是否进入递归,部分判断,避免遍历太多无用点
参考代码:
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; int a[6][6]; const int dx[9]={0,1,1,-1,-1,2,2,-2,-2}; const int dy[9]={0,2,-2,2,-2,1,-1,1,-1}; bool bk; int ans[6][6]= {{0,0,0,0,0,0},{0,1,1,1,1,1},{0,0,1,1,1,1},{0,0,0,2,1,1},{0,0,0,0,0,1},{0,0,0,0,0,0} }; bool pd() {for(int i=1;i<=5;i++) for(int j=1;j<=5;j++) if(a[i][j]!=ans[i][j]) return false;return true; } int w; bool pdA(int k) {int s=0;for(int i=1;i<=5;i++){for(int j=1;j<=5;j++){if(a[i][j]!=ans[i][j]){s++;if(s+k>w) return false;}}}return true; } void dfs(int x,int y,int k) {if(bk==true) return ;if(k==w){if(pd()==true) bk=true;return ;}else{for(int i=1;i<=8;i++){int tx=x+dx[i],ty=y+dy[i];if(tx<1||tx>5||ty<1||ty>5) continue;swap(a[x][y],a[tx][ty]);if(pdA(k)==true) dfs(tx,ty,k+1);swap(a[x][y],a[tx][ty]);}} } int main() {int T;scanf("%d",&T);while(T--){char st[10];int kx,ky;for(int i=1;i<=5;i++){scanf("%s",st+1);for(int j=1;j<=5;j++){if(st[j]=='*'){a[i][j]=2;kx=i,ky=j;}else a[i][j]=st[j]-'0';}}bk=false;for(w=1;w<=15;w++){dfs(kx,ky,0);if(bk==true){printf("%d\n",w);break;}}if(bk==false) printf("-1\n");}return 0; }