好吧,对于一个初学者,我连自己打的是A*还是IDA*都不知道……
这题如果用BFS来做肯定是要TLE的,那么我们就能想到用BFS的进化版——A*来做。
可以说BFS是一种特殊的A*:因为用A*的思想来考虑BFS,就会发现BFS的估价函数永远等于0。
A*比BFS就多了一个估价函数,但是A*却比BFS更快、更强!
设估价函数f(i)=g(i)+h(i),g(i)为当前搜索层数,h(i)为当前状态和目标状态的错位个数。
若当前的估价函数f(i)已经大于了当前的ans,那么接着搜索下去也不可能比当前的ans更优,所以就返回。
以上就是估价函数的基本思想,其实还是挺好理解的。
IDA*就是把A*的广搜改成了深搜,省了空间。
就这样吧,希望我的博客对各位同学有所帮助:)
附上AC代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int n=5;
const int e[6][6]={ {0,0,0,0,0,0},
{0,1,1,1,1,1},
{0,0,1,1,1,1},
{0,0,0,-6,1,1},
{0,0,0,0,0,1},
{0,0,0,0,0,0}};
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};
int t,ans,xx,yy,map[6][6];
char c;
bool b[6][6];
bool pd(){
for (int i=1; i<=n; ++i)
for (int j=1; j<=n; ++j)
if (map[i][j]!=e[i][j]) return 0;
return 1;
}
int astar(int sum){
for (int i=1; i<=n; ++i)
for (int j=1; j<=n; ++j)
if (map[i][j]!=e[i][j]) ++sum;
return sum;
}
void so(int x,int y,int sum){
if (pd()) ans=min(ans,sum);
if (sum>=ans) return;
for (int i=1; i<=8; ++i){
int fx=x+dx[i],fy=y+dy[i];
if (fx<1||fx>n||fy<1||fy>n) continue;
swap(map[x][y],map[fx][fy]);
if (astar(sum)<=ans) so(fx,fy,sum+1);
swap(map[x][y],map[fx][fy]);
}
return;
}
int main(void){
scanf("%d",&t);
while (t--){
for (int i=1; i<=n; ++i)
for (int j=1; j<=n; ++j){
c=getchar();
while (c!='1'&&c!='0'&&c!='*') c=getchar();
if (c=='*') xx=i,yy=j;
map[i][j]=c-'0';
}
ans=16;
so(xx,yy,0);
printf("%d\n",ans>15?-1:ans);
}
return 0;
}
P.S:洛谷真的是个神奇的OJ,我在BZOJ上测是可以过的程序,放到洛谷上就会TLE——O2真的是个好东西。