騎士精神
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 最大可走步數時,就可以剪枝...