装箱问题

描述

有一个箱子容量为v(正整数,o≤v≤20000),同时有n个物品(o≤n≤30),每个物品有一个体积 (正整数)。要求从 n 个物品中,任取若千个装入箱内,使箱子的剩余空间为最小。

格式

输入格式

第一行,一个整数,表示箱子容量;
第二行,一个整数,表示有n个物品;
接下来n行,分别表示这n个物品的各自体积。

输出格式

一个整数,表示箱子剩余空间。

样例1

样例输入1

24
6
8
3
12
7
9
7

  
  
Copy

样例输出1

0

  
  
Copy

限制

每个测试点1s

来源

noip2001普及组第四题

解题思路:

这题其实就是把 01 背包变换了一下,我们可以先求出它能装得下的最大容量,然后用背包容量减去最大容量,剩下的就自然是剩余的最小容量了。

所以,就是先用 01 背包的状态转移方程,求出能使用的最大容量。
这时,01背包的方程就要稍作修改

原来是这样的 f[i][j] = max(f[i - 1][j],f[i - 1][j - w[i]] + c[i])
w 存放物品的体积, c 存放物品的价值

这时,要改为:f[i][j] = max(f[i - 1][j],f[i - 1][j - w[i]] + w[i]);
就是把后面的 + 物品的价值修改为 + 物品的体积。

因为这里要求的是最大的容量,而不是最大的价值。
最后再用总的容量 m 减去 求得的最大容量 就可以了

#include <iostream>
#include <algorithm>

using namespace std;

int f[35][20005];
int w[35];

int main()
{
    ios::sync_with_stdio(false);
    int n,m;
    cin >> m >> n;
    for (int i = 1; i <= n; ++i)
    {
     cin >> w[i];
    }
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 0; j <= m; ++j)
         f[i][j] = m;
    }
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 0; j <= m; ++j)
        {
            //cout << f[i][j] << " ";
            if (j >= w[i])
            {
                f[i][j] = max(f[i - 1][j],f[i - 1][j - w[i]] + w[i]);
            }
            else
             f[i][j] = f[i - 1][j];
        }
    }
    cout << m - f[n][m] << endl;
    return 0;
}

这个还可以像 01 背包那样用一维进行空间上的优化,使用一维数组达到目的。

f [j] = max(f [j],f [j - w[i]] + c[i])
这个是 01 背包的使用一维数组时的状态转移方程

下面的是这个问题的一维数组优化的状态转移方程
f [j] = max(f [j],f [j - w[i]] + w[i])

注意:循环的顺序也要进行修改,因为是使用一维数组,所以循环顺序要修改
原来是从 1 一直 到 m,使用一维时要从 m 到 0 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值