背包问题 -- 二维数组写法 及 特殊情况01背包

01背包问题

有n个重量和价值分别为wi、vi的物品,每件物品都有1个。从这些物品中挑选出总重量不超过W的物品,求所有挑选方案中价值总和的最大值。
限制条件:
1 <= n <= 100
1 <= wi, vi <= 100
1 <= W <= 10000

具体叙述见前博客01背包。
这里要说的是dp数组是一个二维数组,不需要考虑倒序还是正序放入的问题。

先给出代码:

for(int i = 0; i < n; i++)
{
    for(int j = 0; j <= W; j++)
    {
        if(j < w[i])
        {
            dp[i+1][j] = dp[i][j];
        }
        else
        {
            dp[i+1][j] =max{dp[i][j], dp[i][j-w[i]]+v[i]};
        }
    }
}

i是考虑第i件物品,j是考虑背包容量,dp的值是考虑对应的价值。

对于不同的j时每个第i+1件物品考虑放入的时候,要看第i件物品放入的时候的情况。这样不会出现重复放入相同物品的问题。


完全背包

有n个重量和价值分别为wi、vi的物品,每件物品都有n个。从这些物品中挑选出总重量不超过W的物品,求所有挑选方案中价值总和的最大值。
限制条件:
1 <= n <= 100
1 <= wi, vi <= 100
1 <= W <= 10000

对于这个题我结合一维滚动数组的方法,当自身可以重复放入的时候我把i+1相同情况下去和之前的j做计算。

代码如下:

for(int i = 0; i < N; i++)
{
    for(int j = 0; j <= W; j++)
    {
        if(j < w[i])
        {
            dp[i+1][j] = dp[i][j];
        }
        else
        {
            dp[i+1][j] = max{dp[i][j], dp[i+1][j-w[i]]+v[i]};
        }
    }
}

特殊的01背包

有n个重量和价值分别为wi、vi的物品,每件物品都有1个。从这些物品中挑选出总重量不超过W的物品,求所有挑选方案中价值总和的最大值。
限制条件:
1 <= n <= 100
1 <= wi <= 10^7
1 <= vi <= 100
1 <= W <= 10^9

这个问题和最初的01背包相比只是修改了限制条件的大小,但是此前的方法可能会导致超时(呃,大概是一定会),那么我们试试对DP对象改动。
新的定义dp[i+1][j]是前i个物品中挑出价值总和为j时总质量的最小值(不存在就赋值INF)。
前0个物品什么都挑选不了,初始值dp[0][0] = dp[0][j] = INF;

递推式:dp[i+1][j] = min{dp[i][j], dp[i][j - v[i]]+w[i]};

最后只需要看dp[i+1]这一维度dp[i+1][j]值存在的最大j就是价值总和最大。

代码如下:

dp[0][0] = 0;
for(int i = 0; i < n; i++)
{
    for(int j = 0; j <= N*MAX_V; j++)
    {
        if(j < v[i])
        {
            dp[i+1][j] = dp[i][j];
        }
        else
        {
            dp[i+1][j] = min{dp[i][j], dp[i][j-v[i]]+w[i]};
        }
    }
}
for(int i = 0; i <= N*MAX_V; i++)
    if(dp[n][i] <= W)
        ans = i;

再啰嗦一遍:更新的是第i件物品是否放入时价值为j的时候的最小质量,要考虑前i-1件物品时价值为j的最小质量和第i件物品放入时的最小质量,最后看n件物品放入的时候价值最大的质量是否存在。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值