51nod 2072装箱问题

这是一个经典的01背包,而背包问题的本质就是动态规划,因此完全不用管什么背包不背包的,记不住还影响心情。

接下来将从两个角度来解决这道动态规划。

角度一

d p i dp_i dpi 代表容量为 i i i 的背包能够装入的最大体积。
考虑逐个物品添加。
最开始什么也没装,所以全部初始化为 0 0 0
每一轮添加物品至容量为 i i i 的背包都有两种选择——装入该物品和不装入该物品,二者取最大值即可。

  • 若装入该物品(假定其体积为 v v v ),我们可以事先装入该物品,问题就变成了寻找容量为 i − v i-v iv 的背包能够装入的最大体积。
  • 若不装入,保持 d p i dp_i dpi 不变即可。
  • 综上 , d p i = m a x { v + d p i − v , d p i } dp_i=max\{v+dp_{i-v}, dp_i\} dpi=max{v+dpiv,dpi} (注意这里的 d p i − v dp_{i-v} dpiv 必须是上一轮的结果,如果用该轮结果,物品可能被添加两次)。
#include <cstdio>
#include <algorithm>
using namespace std;

const int N = 2e4+4;
int dp[N];  // dp[i]容量为i的背包能装入的最大空间
int main()
{
    int V;
    int n;
    scanf("%d%d", &V, &n);
    while (n--) {
        int x;
        scanf("%d", &x);
        // 为保证dp[j-x]总是上一轮结果,采用倒序遍历
        for (int j = V; j >= x; --j) {
            dp[j] = max(dp[j], dp[j-x]+x);
        }
    }
    printf("%d", V-dp[V]);
    return 0;
}
角度二

d p i dp_i dpi 代表容量为 i i i 的背包能够最后剩余的最小体积。
考虑逐个物品添加。
最开始什么也没装,所以容量有多少剩多少。
每一轮添加物品至容量为 i i i 的背包都有两种选择——装入该物品和不装入该物品,取二者剩余体积的最小值即可。

  • 若装入该物品(假定其体积为 v v v ),我们可以事先装入该物品,问题就变成了寻找容量为 i − v i-v iv 的背包剩余的最小体积。
  • 若不装入,保持 d p i dp_i dpi 不变即可。
  • 综上 , d p i = m i n { d p i − v , d p i } dp_i=min\{dp_{i-v}, dp_i\} dpi=min{dpiv,dpi} (注意这里的 d p i − v dp_{i-v} dpiv 必须是上一轮的结果,如果用该轮结果,物品可能被添加两次)。
#include <cstdio>
#include <algorithm>
using namespace std;

const int N = 2e4+4;
int dp[N];  // dp[i]容量为i的背包剩余的最小体积
int main()
{
    int V;
    int n;
    scanf("%d%d", &V, &n);
    for (int i = 1; i <= V; ++i) dp[i] = i;  // 最开始有多少剩多少
    while (n--) {
        int x;
        scanf("%d", &x);
        // 为保证dp[j-x]总是上一轮结果,采用倒序遍历
        for (int j = V; j >= x; --j) {
        	// min{不放物品x则剩余容量不变,放置物品x剩余容量取决于上一轮j-x空间的情况}
            dp[j] = min(dp[j], dp[j-x]);
        }
    }
    printf("%d", dp[V]);
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值