完全背包问题——动态规划

完全背包问题

  1. 问题描述:

    有 N 种物品和一个容量是 V 的背包,每种物品都有无限件可用。

    第 i 种物品的体积是 vi,价值是 wi

    求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。

    输出最大价值。

  2. 动态规划解法:

    设F[i][j]表示只看前i个物品,总体积是j的情况下,总价值是多少(与0~1背包表示意义一样)。先做出如下推导:

    在计算状态i,j的值F[i][j]时,即在体积不超过j的情况下选择第i件物品时,除了要考虑前一状态F[i-1][j](在j的情况下只考虑前i-1件物品)外,还要考虑放置1件i物品、放置2件i物品·····放置k件i物品、直至放满为止这一类大情况。故结果有:

    F[i][j] = max(f[i-1][j], f[i-1][j-v] + w, ····, f[i-1][j-kv] + kw) 1

    据此另外可以推得如下:

    F[i][j-v] = max(f[i-1][j-v], f[i-1][j-2v] + w, ····, f[i-1][j-(k+1)v] + kw) 2

    仔细观察1、2式可得,1中max内的右半部分比2式多出一个w,故可用2式+w来代替。即F[i][j] = max(f[i-1][j], f[i][j-v] + w);

  3. 代码示例:

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1010;
    int f[N][N], n, m, v[N], w[N];
    int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++) scanf("%d%d", v + i, w + i);
    for(int i = 1; i <= n; i ++)
    for(int j = 1; j <= m; j ++){
    f[i][j] = f[i-1][j];
    if(j >= v[i]) f[i][j] = max(f[i][j], f[i][j - v[i]] + w[i]);
    }
    printf("%d", f[n][m]);
    return 0;
    }
  4. 优化后:(优化后在具体理解方式上还是要按照二维数组的思路来)

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1010;
    int f[N], n, m, v[N], w[N];
    int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++) scanf("%d%d", v + i, w + i);
    for(int i = 1; i <= n; i ++)
    for(int j = v[i]; j <= m; j ++)
    f[j] = max(f[j], f[j - v[i]] + w[i]);
    printf("%d", f[m]);
    return 0;
    }
  5. 0~1背包与完全背包对比:

    0~1背包:取左边状态和左上(不严格左上)状态的最大值。

    完全背包:取左边状态和正上面(不一定相邻的上面)状态的最大值。

posted @   ture?  阅读(168)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示