认真背算法day05

今天写一下回溯算法。

关于回溯算法,我认为回溯本质而言就是一个递归(一个深度遍历DFS),只不过这个递归过程看好是遇到不合适的就往回走,然后继续遍历。那么如何选取到最合适的解决方案呢,那就是在遍历的过程中加入一个“记事本”,这个记事本用来记录当前已经拿到的最好的结果,在后续的遍历过程中,如果有更好的结果,就把当前结果进行替换。

但是递归的复杂度太高了,有没有什么好的解决办法呢,就是加上剪枝过程,根据实际题目条件加上限制用来剪枝,让不必要的遍历直接跳过。

一个典型的背包问题0-1问题,就是可以用回溯来解决,回溯可以转化为递归树,其实就是一个二叉树,而回溯就是二叉树的DFS遍历,至此,回溯算法的本质已经讲清楚了。如果还有不理解,请看下面的例子,和一篇好文章:

 

文章(回溯和递归树、二叉树的关系):https://blog.csdn.net/yhflyl/article/details/86763197

 

例子:

问题:背包问题

解答:


public int maxW = Integer.MIN_VALUE; //存储背包中物品总重量的最大值
// cw表示当前已经装进去的物品的重量和;i表示考察到哪个物品了;
// w背包重量;items表示每个物品的重量;n表示物品个数
// 假设背包可承受重量100,物品个数10,物品重量存储在数组a中,那可以这样调用函数:
// f(0, 0, a, 10, 100)
public void f(int i, int cw, int[] items, int n, int w) {
  if (cw == w || i == n) { // cw==w表示装满了;i==n表示已经考察完所有的物品
    if (cw > maxW) maxW = cw;
    return;
  }
  f(i+1, cw, items, n, w);
  if (cw + items[i] <= w) {// 已经超过可以背包承受的重量的时候,就不要再装了,剪枝过程!
    f(i+1,cw + items[i], items, n, w);
  }
}

 

收工~

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值