搜索个人感觉最重要的就是确定对状态的定义,之后的动规最重要的也是状态的确定。
状态确定的好那么搜索也就相对容易,而对于状态的确定需要通过一些题目来进行总结。
例题1.
立体八数码问题
八数码是对空格的搜索,那么很明显空格的位置是一个描述状态的量,id表示空格的编号,此外步数也是一个描述状态的量,这个时候思考有了这两个参量是否能唯一确定状态呢,空格一样,步数一样,但其他的各自状态可能不一样,所以其他的8个方块的状态也应该记录,此时再来检查状态是否唯一呢,9个方块状态一模一样并且步数相同。完全可以唯一确定状态,那么此时状态就已经确定好了。此题由于状态空间很大,那么采用双向bfs,此时按层数搜索,用优先队列存储状态,编号需要花一些功夫,此题强烈建议写一写。
struct Node
{
int t,n,s;
Node(int _t,int _n,int _s):t(_t),n(_n),s(_s){}
bool operator < (const Node &a) const {
return t>a.t;
}
};
以上是定义状态的部分。
例题2.
UVA11214 守卫键盘
也是同样的问题,其实这道题相对简单,跟八皇后问题比较相似,皇后的个数以及当前走到哪个位置,当然这道题是要使用迭代加深的,所以加上搜索层数的限制就构成了搜索需要的参数
int dfs(int d, int cur, int maxd) {
if(d == maxd) {
if(arrvied()){
printf("Case %d: %d\n", ++kase, d);
return 1;
}
return 0;
}
else {
for(int pos = cur; pos < n*m; pos ++) {
int r = pos/m, c = pos%m;
int tmp_a = vis[0][r], tmp_b = vis[1][c], tmp_c = vis[2][r+c], tmp_d = vis[3][c-r+n];
vis[0][r] = vis[1][c] = vis[2][r+c] = vis[3][c-r+n] = 1;
if(dfs(d+1, pos, maxd)) return 1;
vis[0][r] = tmp_a; vis[1][c] = tmp_b; vis[2][r+c] = tmp_c; vis[3][c-r+n] = tmp_d;
}
}
return 0;
}
以上搜索代码也比较简单,贴出代码只是为了看看搜索的参数。
搜索之前确定好状态量,事半功倍。