算法復習——叠代加深搜索(騎士精神bzoj1085)
阿新 • • 發佈:2017-09-02
input ace out div 函數 true width cout 數據
10110
01*11
10111
01001
00000
01011
110*1
01110
01010
00100
-1
題目:
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
210110
01*11
10111
01001
00000
01011
110*1
01110
01010
00100
Sample Output
7-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; }
算法復習——叠代加深搜索(騎士精神bzoj1085)