【bzoj1085】 SCOI2005—骑士精神
http://www.lydsy.com/JudgeOnline/problem.php?id=1085 (题目链接)
题意
给出一个初始局面,问能否在15步内走到最终局面,并输出最少步数。
Solution
迭代加深+A*,估价函数就是有cnt个子不在最终局面的位置,也就是说就算每一步都能将一个子归位,那么至少也需要cnt步。
终于有点理解估价函数的意义了,估出来的必须必实际的要小,这才能保证答案的正确性。
代码
// bzoj1085 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #define LL long long #define inf 2147483640 #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); using namespace std; int ans[5][5]={{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}}; int xx[8]={1,2,2,1,-1,-2,-2,-1}; int yy[8]={2,1,-1,-2,-2,-1,1,2}; int a[5][5],d,flag; char ch[10]; bool judge() { for (int i=0;i<5;i++) for (int j=0;j<5;j++) if (a[i][j]!=ans[i][j]) return 0; return 1; } bool eva(int s) { int cnt=-1; for (int i=0;i<5;i++) for (int j=0;j<5;j++) if (a[i][j]!=ans[i][j]) if (++cnt==d-s) return 0; return 1; } void dfs(int s,int x,int y) { if (s==d) {if (judge()) flag=1;return;} for (int i=0;i<8;i++) { int nx=x+xx[i],ny=y+yy[i]; if (nx<0 || nx>4 || ny<0 || ny>4) continue; swap(a[x][y],a[nx][ny]); if (eva(s)) dfs(s+1,nx,ny); if (flag) return; swap(a[x][y],a[nx][ny]); } } int main() { int T;scanf("%d",&T); while (T--) { int x,y;flag=0; for (int i=0;i<5;i++) { scanf("%s",ch); for (int j=0;j<5;j++) { if (ch[j]=='*') a[i][j]=2,x=i,y=j; else a[i][j]=ch[j]-'0'; } } for (d=0;d<=15;d++) { dfs(0,x,y); if (flag) {printf("%d\n",d);break;} } if (!flag) puts("-1"); } return 0; }
This passage is made by MashiroSky.