IDA 演算法 騎士精神

2021-08-07 02:16:28 字數 2003 閱讀 1849

騎士精神

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

樣例中第二個資料的初始情況對應該圖:

這題的狀態共有3^25,遍歷完所有狀態的時間則是8^15。

考慮用ida*(貌似有其它做法)

舉個簡單的例子(不是指這題):

如果用dfs,搜得過深卻容易找不到解。所以應用bfs或iddfs(迭代加深搜尋)。

但是bfs有乙個缺點,就是空間大。

因此,結合dfs和bfs,就有了iddfs。

就是先搜深度為0的節點,再搜深度為1的節點、2的節點……直到搜出解。

為什麼不用二分?因為節點的數量是指數級增長的,這樣可能搜出很多無意義的情況。

iddfs的缺點:搜過的點會再搜。

然而這樣時間還會爆掉。我們可以用啟發式搜尋中的ida*,設h(估價函式)為當前這個狀態,沒回到應該回到位置上的點的個數-1。為什麼要-1?對於這題,若走k次,則最多更新k+1個點(原因顯然,自己思考);反過來就是說,若想要更新k個節點,則最少走k-1次。所以,h要-1。這樣就保證了h(i)<=h*(i)(估計距離<=實際距離),保證了答案的正確性。只需利用h進行剪枝即可。

#include 

#include

#include

using

namespace

std;

char

map[7][7];//地圖

char tar[7][7]=,,,,,};//目標狀態

int fx[9]=;

int fy[9]=;

bool ida_star(int,int,int,int,int);

int main()

getchar();

}h=0;

for (i=1;i<=5;++i)

for (j=1;j<=5;++j)

h+=(map[i][j]!=tar[i][j]);//統計不在位置上的點

for (i=0;i<=15;++i)

if (ida_star(0,h-1,i,x,y))//迭代加深(h-1的原因見上面)

if (i>15)

printf("-1\n");

}}bool ida_star(int g,int h,int lim,int x,int y)//g為現在的步數,h為估價函式,lim為限制深度,(x,y)為'*'的座標(x行y列)

}return

0;}

IDA 演算法 騎士精神

騎士精神 description 在乙個5 5的棋盤上有12個白色的騎士和12個黑色的騎士,且有乙個空位。在任何時候乙個騎士都能按照騎士的走法 它可以走到和它橫座標相差為1,縱座標相差為2或者橫座標相差為2,縱座標相差為1的格仔 移動到空位上。給定乙個初始的棋盤,怎樣才能經過移動變成如下目標棋盤 為...

騎士精神 IDA

不說了,這玩意就是個人生題,昨天晚上各種鬼,還有變數突然變成0的坑爹事情都出現了。十五步以上算 1解。總體思路,ida 1.寫個估值函式,這裡我寫的是和目標圖的理想差異 2.列舉步數,根據步數和估值來決定剪枝。3.一點經驗,估值剪枝不要嚴格卡在步數上,可以適當放高上限,確保答案在搜尋樹上,換言之就是...

SCOI2005 騎士精神 IDA

棋盤太大,狀態數太多,無法像八數碼那樣用雜湊 bfs去做,但是用dfs也會t掉,這個時候可以考慮ida 即 迭代加深搜尋 a 剪枝。這題的h n 就是當前與目標棋盤不同的棋子數量。在一顆含有答案的子樹中,我們至多需要再走h n 步,就可以找到答案 因此,當當前步數 h n 最大可走步數時,就可以剪枝...