当前位置:   article > 正文

动态规划完全背包问题-java_完全背包问题java代码

完全背包问题java代码

完全背包问题跟01背包问题思路大致一样,只不过对于物品的拿取次数不在限制,我们只需要考虑这点即可。


前言

完全背包问题跟01背包问题思路大致一样,只不过对于物品的拿取次数不在限制,我们只需要考虑这点即可。


提示:以下是本篇文章正文内容,下面案例可供参考

一、什么是完全背包问题?

有n种物品和一个bag大小的背包容量,每种物品都有无限件可以使用,每个物品都有体积v和价值w,求解背包所能容纳的最大价值是多少?

二、问题模拟

1.样例数据

假设我们还有有4种物品和一个容量为5的背包,这四种物品对应的体积和价值分别为:

  • 物品一:体积是1,价值是2
  • 物品二:体积是2,价值是4
  • 物品三:体积是3,价值是4
  • 物品三:体积是4,价值是5

2.算法思路

数组v[i]表示第i种物品的体积,w[i]表示第i种物品的价值。

我们引入dp状态数组,行数i表示第几种物品,列数j表示背包的容量j,dp[i][j] 表示在当前背包容量j下 选取第i种物品后所能容纳的最大价值。

dp[i][j]的计算可以通过以下的推算进行:

  • 选取0个第i种物品即不选取新物品,即对应dp[i-1][j]
  • 选取1个第i种物品,dp[i-1][j-v[i]]+w[i]
  • 选取2个第i种物品,dp[i-1][j-2*v[i]]+2*w[i]

上述过程不会无限增加,因为我们有背包容量j,那么我们就可以得到一个极限条件,假设当前背包容量j下最多可得到t个物品,t*v[i] \leqslant j

t = \frac{j}{v[i]}

那么完全背包的状态就是我们在不拿新物品、拿1件新物品、拿2件新物品等等直到最多拿k件新物品中比较得到的最大值即为dp[i][j]的值 

dp[i][j] = \max dp[i][j-k*v[i]]+k*w[i] 0\leqslant k\leq t

那么我们就可以得到dp数组的递推代码:

  1. //第几种物品
  2. for(int i = 1;i <= n;i++){
  3. //背包容量
  4. for(int j = 1;j <= bag;j++){
  5. //表示在当前背包容量j下最多再放t个第i种物品
  6. int t = j / v[i];
  7. for(int k = 0;k <= t;k++){
  8. dp[i][j] = Math.max(dp[i][j],dp[i-1][j-k*v[i]] + w[i] * k);
  9. }
  10. }
  11. }

3.代码优化

我们 通过观察可以发现,其实k循环可以舍弃掉,完全背包问题dp[i][j]我们可以通过每次累加v[i],当j < v[i],我们相当于没加取上一个物品的最佳状态,dp[i][j] = dp[i-1][j]。当j >= v[i],那我们就取当前第i个物品然后背包容量j-v[j]时的最大价值+w[i],dp = max{dp[i-1][j],dp[i][j-v[i]]+w[i]}

 

  1. //第几种物品
  2. for(int i = 1;i <= n;i++){
  3. //背包容量
  4. for(int j = 1;j <= bag;j++){
  5. dp[i][j] = dp[i-1][j];
  6. if(j - v[i] >= 0){
  7. dp[i][j] = Math.max(dp[i][j],dp[i][j-v[i]]+w[i]);
  8. }
  9. }
  10. }

图2.1dp数组值 

三、代码如下

1.代码如下(示例):

  1. package AcWing;
  2. import java.io.*;
  3. public class 完全背包问题 {
  4. static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
  5. static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  6. static StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
  7. public static void main(String[] args) throws Exception{
  8. int n = nextInt(),bag = nextInt();
  9. int[][] dp = new int[n+1][bag+1];
  10. //体积
  11. int[] v = new int[n+1];
  12. //价值
  13. int[] w = new int[n+1];
  14. for(int i = 1;i <= n;i++){
  15. v[i] = nextInt();
  16. w[i] = nextInt();
  17. }
  18. //第几种物品
  19. for(int i = 1;i <= n;i++){
  20. //背包容量
  21. for(int j = 1;j <= bag;j++){
  22. //表示在当前背包容量j下最多再放t个第i种物品
  23. int t = j / v[i];
  24. for(int k = 0;k <= t;k++){
  25. dp[i][j] = Math.max(dp[i][j],dp[i-1][j-k*v[i]] + w[i] * k);
  26. }
  27. }
  28. }
  29. pw.println(dp[n][bag]);
  30. pw.flush();
  31. }
  32. public static int nextInt()throws Exception{
  33. st.nextToken();
  34. return (int)st.nval;
  35. }
  36. }

2.读入数据

  1. 4 5
  2. 1 2
  3. 2 4
  4. 3 4
  5. 4 5

3.代码运行结果

10

总结

上面主要是对完全背包问题进行一个解释,我们还是主要理解dp数组的含义以及状态转移方程如何得出来。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/833598
推荐阅读
相关标签
  

闽ICP备14008679号