四种背包问题

动态规划:

转自https://blog.csdn.net/na_beginning/article/details/62884939
基本思想:
动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中, 可能会有很多可行解。没一个解都对应于一个值,我们希望找到具有最优值的解。胎动规划算法与分治法类似,其基本思想也是将待求解问题分解为若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适用于动态规划算法求解的问题,经分解得到的子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算很多次。如果我们能保存已解决子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解决的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。这就是动态规划算法的基本思路。具体的动态规划算法多种多样,但它们具有相同的填表格式。

与分治法最大的差别是:适用于动态规划求解的问题,经分解后得到的子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解)

应用场景:
适用于动态规划的问题必须满足最优化原理、无后效性和重叠性。

(1) 最优化原理(最优子结构性质):一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的决策必须构成最优策略。简而言之,一个最优化策略的子策略总是最优的。一个问题满足最优化原理又称其具有最优子结构性质。

(2) 无后效性:将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它未来的决策,而只能通过当前的这个状态。换句话说,每个状态都是过去历史的一个完整总结。这就是无后向性,又称无后效性。

(3) 子问题的重叠性:动态规划将原来具有指数级时间复杂度的搜索算法改进成了具有多项式时间复杂度的算法。其中的关键在于解决冗余,这就是动态规划算法的根本目的。动态规划实质上是一种以空间换时间的技术,它在实现的过程中,不得不存储产生过程中的各种状态,所以它的空间复杂度要大于其他算法。

二维背包


//N为物品数目
//W为背包所承载的最大重量
//V为背包所承载的最大容量
//weights[]为每个物品的重量
//volume[]为每个物品的体积
//values[]为每个物品的价值
public int twoDimensionKnapack(int N, int W, int V, int[] weights, int[] volume, int[] values ){
   
    int[][] dp = new int[W+1][V+1];
    
    for(int i = 1; i <= N; i++){
   
        int w = weights[i-1], vi = volume[i-1], v = values[i-1];
        for(int j = W; j >= w; j--){
   
            for(int k = V; k >= vi; k--){
   
                dp[j][k] = Math.max(dp[j][k], dp[j-w][k-vi]+v);
            }
        }
    }
    return dp[W][V];
}

多重背包

需要再考虑一下每件物品的数量

import java.util.*;

public class Main {
   
    /**
     * 多重背包问题
     *
     * @param V      背包容量
     * @param N      物品种类
     * @param weight 物品重量
     * @param value  物品价值
     * @return
     */

    public static String ZeroOnePack(int V, int N, int[] weight, int[] value,int[] num) {
   

        //初始化动态规划数组,程序的目的是列出整个状态表,即背包容量为0~V,物品个数为0~N的所有最大价值dp[i][j];
        int[][] dp = new int[N + 1][V + 1];
        //为了便于理解,将dp[i][0]和dp[0][j]均置为0,从1开始计算
        //
        for (int i = 1; i < N + 1; i++
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值