火车运输-动态规划、双重背包

问题描述

钢厂有一辆用于运送废旧钢材的火车,它具有两节车厢,其中车厢 1 的最大载重量为 A,车厢 2 的最大载重量为 B。现在一共有 N 件废旧钢材需要被运输,其中第 i 件钢材的重量为 wi​。为了最大化运输效率,车长想要一次性运输走重量尽可能多的钢材,请你帮助车长计算出一次运输最多可以带走多大重量的钢材。

每件钢材都是独立的不可分割的,只能被放置在某一节车厢中。在装载钢材时只需要考虑重量条件即可。

输入格式

输入的第一行包含三个整数 N,A,B,用一个空格分隔,分别表示钢材的数目以及两节车厢的最大载重。

第二行包含 N 个整数,分别表示 w1​, w2​, ..., wn​,相邻两个整数之间使用一个空格分隔。

输出格式

输出一个整数表示答案。

样例输入

3 10 8
8 9 1

样例输出

18

样例说明

车厢 1 装入第 2 件和第 3 件钢材,车厢 2 装入第 1 件钢材。

评测用例规模与约定

对于 30% 的评测用例,1≤N≤10;

对于所有评测用例,1≤N≤200,1≤wi,A,B≤1,000。

运行限制

语言最大运行时间最大运行内存
C++1s256M
C1s256M
Java2s256M
Python33s256M
PyPy33s256M
Go3s256M
JavaScript3s256M

 解析:

这是一个双重背包原理,与0-1背包原理相同。

定义一个二维数组dp[ j ][ k ], j表示A车的容量,k表示B车的容量,容量为jk时所能装在的最大重量。

dp[j][k]=\begin{cases} max(dp[j][k],dp[j-w[i]][k]), w[i]<=j & \text{ } \\ max(dp[j][k],dp[j][k-w[i]]), w[i]<=k& \text{ } \end{cases}

 通过倒叙,防止本次第i个钢材的影响。通过max找最大值可以看出这个钢材只放在了一个火车中。

#include <iostream>
#include <cmath>
using namespace std;
typedef long long ll;
const ll MAX = 1e3;
const ll M = 1e4 + 7;
ll dp[MAX][MAX];//表示A车容量为j B车容量为k 时最大载重
ll p[MAX];
int main() 
{
    ll n, a, b;
    cin >> n >> a >> b;
    for (int i = 1; i <= n; i++)
    {
        cin >> p[i];
    }
    for (int i = 1; i <= n; i++)//前i个钢材
    {
        for (int j = a; j >= 0; j--)//A的容量
        {
            for (int k = b; k >= 0; k--)//B的容量
            {
                if (p[i] <= j)//能装在A中时   看前i-1个时大 还是放上这个钢材更大
                {
                    dp[j][k] = max(dp[j][k], dp[j - p[i]][k]+p[i]);
                }
                if (p[i] <= k)//能装在B中时   看装在A中大 还是装在B中大 
                {
                    dp[j][k] = max(dp[j][k], dp[j][k - p[i]] + p[i]);
                }
            }
        }
    }
    cout << dp[a][b] << endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值