1. 程式人生 > >算法復習——叠代加深搜索(騎士精神bzoj1085)

算法復習——叠代加深搜索(騎士精神bzoj1085)

input ace out div 函數 true width cout 數據

題目:

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

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)