算法复习——迭代加深搜索(骑士精神bzoj1085)
题目:
Description
在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位。在任何时候一个骑士都能按照骑
士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空
位上。 给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘: 为了体现出骑士精神,他们必须以最少的步
数完成任务。
Input
第一行有一个正整数T(T<=10),表示一共有N组数据。接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑
士,*表示空位。两组数据之间没有空行。
Output
对于每组数据都输出一行。如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1。
Sample Input
2
10110
01*11
10111
01001
00000
01011
110*1
01110
01010
00100
10110
01*11
10111
01001
00000
01011
110*1
01110
01010
00100
Sample Output
7
-1
-1
题解:
首先说一下迭代加深搜索:
迭代加深搜索是搜索算法的一种优化方式,具体方法为在知道搜索最大深度的情况下(如题目中最多15步)从低到高枚举搜索深度上界,则第一个满足的枚举深度就一定是最浅深 度即最优解,另外为了更好的优化,还可以构造一个预估函数,即当前搜索状态到满足题意状态至少要用多少步(注意该函数宁愿估小也不要估大否则可能发生错误),如果当前 搜索深度加上预估函数的值都大于枚举深度那肯定也不满足;
迭代加深搜索适用于便于预估所有状态下搜索上界的情况,且搜索深度不大的情况;
不懂的话结合这道题和代码理解即可;
代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cctype> #include<cstring> #include<string> #include<algorithm> using namespace std; const char goal[5][5]={{'1','1','1','1','1'}, {'0','1','1','1','1'}, {'0','0','*','1','1'}, {'0','0','0','0','1'}, {'0','0','0','0','0'}}; int sx,sy,T,step; char map[5][5]; struct node { int gox; int goy; }go[8]; inline void pre() { go[0].gox=1,go[0].goy=2; go[1].gox=1,go[1].goy=-2; go[2].gox=2,go[2].goy=1; go[3].gox=2,go[3].goy=-1; go[4].gox=-1,go[4].goy=2; go[5].gox=-1,go[5].goy=-2; go[6].gox=-2,go[6].goy=1; go[7].gox=-2,go[7].goy=-1; } inline bool jud(int x,int y) { return x>=0&&x<=4&&y>=0&&y<=4; } inline int check() { int dif=0; for(int i=0;i<=4;i++) for(int j=0;j<=4;j++) if(map[i][j]!=goal[i][j]) dif++; return dif; } inline bool dfs(int x,int y,int now) { if(now==step+1) { if(check()==0) return true; else return false; } if(now+check()-3>step) return false; for(int i=0;i<=7;i++) { int tx=x+go[i].gox; int ty=y+go[i].goy; if(jud(tx,ty)) { swap(map[x][y],map[tx][ty]); if(dfs(tx,ty,now+1)) return true; swap(map[x][y],map[tx][ty]); } } return false; } int main() { //freopen("a.in","r",stdin); scanf("%d",&T); pre(); while(T--) { sx=sy=0; for(int i=0;i<=4;i++) scanf("%s",map[i]); bool flag=false; for(int i=0;i<=4;i++) { if(flag==true) break; for(int j=0;j<=4;j++) if(map[i][j]=='*') { sx=i,sy=j; flag=true; break; } } step=1; for(int i=1;i<=15;i++) { if(dfs(sx,sy,1)) break; step++; } if(step==16) cout<<"-1"<<endl; else cout<<step<<endl; } return 0; }