动态规划法求背包问题

0-1背包问题是指给定一个容量一定的背包和一系列已知重量和价值的物品,从中选择一些物品放入背包使得背包中物品的总价值最大.

背包问题可以用动态规划,回溯法或者贪心算法求解.这里介绍使用动态规划法求解0-1背包问题.

动态规划法需要几个数组来辅助:

  • m: 背包最大容量

  • n: 物品的个数

  • w[i] : 第i个物品的重量

  • v[i]: 第i个物品的价值

  • c[i][j]: 前i个物品放入容量为j的背包最大的价值

动态规划法的最终目的是填写二维数组c,c[n][m]即为原问题的结果.

为了方便起见下标从1开始, i表示物品编号, j表示当前容量.先行后列,从上到下,从左到右填写二维数组c.

  • 若总容量小于物品质量(j < w[i]), 当前最大价值不变(c[i][j] = c[i-1][j])

  • 前i-1个物品选择装入第i个物品后正好装满的方案(c[i-1][j-w[i]]), 若装入后价值比前i-1个物品最大价值(c[i-1][j])更大,则装入第i个物品;

  • 否则保留前i-1个物品最大价值(c[i-1][j])

上述三种状态下

举一个简单的例子:

背包最大容量为10,有三个物品重量和价值分别为: (3,4),(4,5), (5,6),求背包最大价值.

填写二维数组c:

0 0 4 4 4 4 4 4  4  4 
0 0 4 5 5 5 9 9  9  9
0 0 4 5 6 6 9 10 11 11 

由此可知最大价值为11.

一言不发就丢代码:

 #include <stdio.h>

#define M 128
#define N 32

int m = 0, n = 0;
int c[N][M] = {0};
int w[N] = {0};
int v[N] = {0};

void npack() {
    int i, j;
    for (j=1; j <= m; j++) {
        for (i=1; i <= n; i++) {
            if (j < w[i]) {
                c[i][j] = c[i-1][j];
                continue;
            }
            else if(c[i-1][j-w[i]] + v[i] > c[i-1][j]) {
                c[i][j] = c[i-1][j-w[i]] + v[i];
            }
            else {
                c[i][j] = c[i-1][j];
            }
        }
    }
}

int main() {
    int i, j;
    // input
    scanf("%d %d", &m, &n);
    for (i = 1; i <= n; i++) {
        scanf("%d %d", &w[i], &v[i]);
    }
    npack();
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            printf("%4d ", c[i][j]);
        }
        printf("\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值