算法竞赛入门到进阶 读书笔记(3)

四、深度优先搜索

深度优先搜索会首先从一层探索到最深直到碰壁无法行走,在换另一条路搜索下去,用这个方法走遍所有的路,并且规定不会走重复的路。深度优先搜索的代码通常会比广度简便一些,但像最短距离之类的问题还是要使用广度优先搜索。

1 .与递归结合
深度优先搜索用递归实现是最普遍的,hdu1312的红黑砖块问题用dfs做就更为简便。

void dfs(int dx,int dy){
a[dx][dy]='#';  //标记已经走过
num++;        //走过的砖块数+1
for(i=0;i<4;i++)
{ int nx=dx+dir[i][0];  //左上右下顺时针顺序搜索下一块砖块
  int ny=dy+dir[i][1];
  if(check(nx,ny)&&a[nx][ny]=='.')  //如果在范围之内并且该砖块未走过,则用递归继续进行深度搜索
  dfs(nx,ny);}
  }

2.回溯与剪枝
为了防止路径过多而超时,很多子节点可以根据题目条件提前判断,中途停止并返回。
例:hdu 2553 n皇后问题
使棋子不同行、不同列、不同对角线,搜索的很多结点其实在开始就可以完成回溯,向不同行中插入棋子,只有不同列和不对角线的节点才可以继续延伸下去,依次可以构造回溯函数。

bool check(int c,int r)
{ for(i=0;i<r;i++)
{ if(a[i]==c||abs(a[i]-c)==abs(i-r)) return false;
else true;}
}

接下来构造向每一行中插入棋子的搜索函数dfs

void dfs(int r)
{ if(r==n) { total++; return;}  //行满足所给n就可以结束单向搜索了
for(c=0;c<n;c++)
{  if(check(c,r){    //如果不满足回溯条件就可以继续搜索下去
 a[r]=c;   //及时更新列数
 dfs(r+1);}
 }
 }

对于n皇后问题提前在主函数中打表就可以减小复杂度,避免超时。

3.迭代加深搜索
对于搜索树特别宽、特别深的类型不适用bfs和dfs,需要结合bfs和dfs的迭代加深搜索
迭代加深搜索就是提前设定搜索深度,在该搜索深度上进行dfs搜索,直到找到答案后停止搜索。

4.IDA*
A* 可以看作是bfs和贪心的结合,IDA*就可以看作是迭代加深搜索和贪心的结合,通过贪心思想提前预测到dfs的状态,也运用到了一部分的剪枝操作。
poj3134 计算x的n次方
通过题目理解可以构造相应的估价函数,不满足条件则要进行剪枝操作

if(val[p]<<(depth-now)<n) return false; //当前值倍增都不能达到n就要进行剪枝操作

通过前一步和所有值相加减进行搜索判断值是否等于n,通过设定深度搜索层数的方法加减求得答案,结束搜索。综上,运用迭代深度搜索和估价函数可以高效完成计算,大大减小复杂度。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值