暴力递归——从左往右的尝试模型2,背包问题

简介: 暴力递归——从左往右的尝试模型2,背包问题

给定两个长度都为N的数组weights和values,weights[i]和values[i]分别代表i号物品的重量和价值。给定一个正数bag,表示一个载重bag的袋子,你装的物品不能超过这个重量。返回你能装下最多的价值是多少?

博主个人认为,从左往右的尝试模型这一类题型的关键点在于讨论当前位置的东西要或者不要,然后再具体分析,详情看代码吧,都写了很详细的注释。

补充一点:方法二是这一类题最常见的暴力解法,跟方法一相比恰好是逆向思维。

package com.harrison.class12;
public class Code06_Knapsack {
  // 不变参数 w[] v[] bag
  // alreadyW 0~index位置的货物已经做过决定了,现在形成的重量
  // 返回index及其往后位置货物的最大价值
  // 返回 -1 认为方案无效,
  // 返回不是-1,返回值就是真实的价值
  public static int process1(int[] w,int[] v,int index,int alreadyW,int bag) {
    if(alreadyW>bag) {// 超过了载重,方案无效
      return -1;
    }
    // 重量没吵 && 没有货物了,所以此时的最大价值就是0
    if(index==w.length) {
      return 0;
    }
    // 没有要当前货物
    int p1=process1(w, v, index+1, alreadyW, bag);
    // 要了当前的货物
    int p2next=process1(w, v, index+1, alreadyW+w[index], bag);
    int p2=-1;
    // 如果要了当前位置的货物 && 重量没有超过bag
    // 那么这种情况下的最大价值就要加上当前这个货物的价值
    if(p2next!=-1) {
      p2=p2next+v[index];
    }
    // 返回要当前货物和不要当前货物两种情况下的最大价值
    return Math.max(p1, p2);
  }
  public static int maxValue1(int[] w,int[] v,int bag) {
    if(w==null || v==null || w.length!=v.length || w.length==0) {
      return 0;
    }
    return process1(w, v, 0, 0, bag);
  }
  // rest 当前剩余的重量,其余参数跟你上面方法一样
  public static int process2(int[] w,int[] v,int index,int rest) {
    // 如果没有剩余重量了,方案无效
    if(rest<0) {
      return -1;
    }
    // 如果有剩余空间但是没有货物了
    // 那么index及其往后位置的货物的最大价值就是0
    if(index==w.length) {
      return 0;
    }
    // 不要当前位置的货物,所以rest没变
    int p1=process2(w, v, index+1, rest);
    // 要了当前位置的货物,所以剩余空间要减去当前货物的重量
    int p2next=process2(w, v, index+1, rest-w[index]);
    int p2=-1;// 要当前位置货物的话,可能会导致方案无效,也就是剩余重量可能会<0
    // 如果要了当前货物 && 还有剩余重量(方案有效)
    if(p2next!=-1) {
      p2=p2next+v[index];
    }
    // 返回要跟不要当前货物两种情况下的最大值
    return Math.max(p1, p2);
  }
  public static int maxValue2(int[] w,int[] v,int bag) {
    if(w==null || v==null || w.length!=v.length || w.length==0) {
      return 0;
    }
    return process2(w, v, 0, bag);
  }
  public static void main(String[] args) {
    int[] w = { 3, 2, 4, 7, 3, 1, 7 };
    int[] v = { 5, 6, 3, 19, 12, 4, 2 };
    int bag=15;
    System.out.println(maxValue1(w, v, bag));
    System.out.println(maxValue2(w, v, bag));
  }
}
相关文章
|
3月前
|
存储 缓存 算法
动归和递归算法讲解
动归和递归算法讲解
|
11月前
|
存储 人工智能 分布式计算
动态规划从理论到实践-深入理解贪心/分治/回溯/动态规划的算法思想
动态规划从理论到实践-深入理解贪心/分治/回溯/动态规划的算法思想
204 0
|
搜索推荐 容器
暴力递归:动态规划的雏形
暴力递归:动态规划的雏形
|
人工智能 算法
【算法】回溯法的应用
回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。许多复杂的,规模较大的问题都可以使用回溯法,有“通用解题方法”的美称。
223 0
|
机器学习/深度学习 算法
斐波拉契数列的递推递归求解算法
斐波拉契数列的递推递归求解算法
99 0
(蓝桥杯)递推与递归,前缀和,二分经典例题分析
(蓝桥杯)递推与递归,前缀和,二分经典例题分析
(蓝桥杯)递推与递归,前缀和,二分经典例题分析
|
算法
算法设计与分析 暴力递归
算法设计与分析 暴力递归
100 0
算法设计与分析 暴力递归
|
存储 算法
递归题目训练2(总结)
递归题目训练2(总结)
64 0
|
算法
递归+回溯求解数独问题
导读:回溯是常用的算法理论之一,很多规模较大、直接分析较为复杂的问题都可以考虑用回溯求解,例如N皇后问题、骑士周游和走迷宫问题等。本质上,回溯问题是一种优化后的暴力求解,通过及时的剪枝和启发式的寻找最优路径,可以有效加速求解过程。回溯还常常与递归搭配使用
145 0
递归+回溯求解数独问题
|
机器学习/深度学习 缓存 机器人
从暴力递归到动态规划,记忆化搜索
从暴力递归到动态规划,记忆化搜索
从暴力递归到动态规划,记忆化搜索