題面:[scoi2005]騎士精神
對於這道題,我們第一眼:\(bfs\)爆搜
第二眼:發現事情沒這麼簡單:這是道省選題
第三眼:仔細一想,直接\(bfs\)難道不會被卡爆嗎??
第四眼:發現題目中有:「如果能在15步以內(包括15步)到達目標狀態,則輸出步數,否則輸出-1」
好的,\(ida\)*:啟發式迭代加深
\(ida\)*是什麼?
其實就是在\(a\)*的基礎上加上迭代加深
還不知道\(a\)*的同學點這裡
迭代加深其實就是每次搜尋的時候限制你的搜尋深度,使你的搜尋樹的深度保持在乙個較為合理的地方,使你的時間不會**,這樣就可以使你在全域性搜尋的深度很大而答案深度很小的情況下(也是使用\(ida\)*的條件)快速得出答案
在這道題中,明顯可以看出,答案深度\(<=15\),所以我們考慮使用\(ida\)*,在每次搜尋是加上限制深度條件\(maxstep\),如果當前搜尋深度\(step==maxstep\),就返回答案
作為\(a\)*的精髓,估價函式\(g(x)\)當然是我們思考的主要物件
我們可以發現,這道題給出了棋盤的目標布局
我們可以每次\(dfs\)將要進入下一層時,我們都對下一層的棋盤和目標棋盤進行對比,如果差異值\(tot+step>maxstep\),那麼我們就不進入下一層
詳見**
#includeusing namespace std;
const int nextx[8]=;
const int nexty[8]=;
//目標棋盤
int goal[7][7]=,
, ,, , };
char ch[6][6];
int num[6][6];
bool flag=0;
int diff()//差異值
} return tot;
}bool check(int x,int y)
void dfs(int step,int x,int y,int maxstep)
for(int i=0;i<8;i++) }
int main()
} for(int i=1;i<=15;i++)
}if(!flag)puts("-1");
} return 0;
}
SCOI2005 騎士精神 IDA
棋盤太大,狀態數太多,無法像八數碼那樣用雜湊 bfs去做,但是用dfs也會t掉,這個時候可以考慮ida 即 迭代加深搜尋 a 剪枝。這題的h n 就是當前與目標棋盤不同的棋子數量。在一顆含有答案的子樹中,我們至多需要再走h n 步,就可以找到答案 因此,當當前步數 h n 最大可走步數時,就可以剪枝...
SCOI2005 騎士精神
乙個比較直接的思路是bfs爆搜,但這樣只能拿20分,所以考慮優化。在測試樣例時能夠看到深度為7的時候很快就跑出來了,在結合本題最大深度是15,所以可以用雙向bfs來優化,即從兩邊各跑7或8的深度,最後用map合併,有點類似折半搜尋。另外有一些需要注意的小細節已經在 中注釋。code include ...
SCOI2005 騎士精神
輸入格式 第一行有乙個正整數t t 10 表示一共有n組資料。接下來有t個5 5的矩陣,0表示白色騎士,1表示黑色騎士,表示空位。兩組資料之間沒有空行。輸出格式 對於每組資料都輸出一行。如果能在15步以內 包括15步 到達目標狀態,則輸出步數,否則輸出 1。輸入樣例 1 複製2 10110 01 1...