codeforces 1132E 背包DP

codeforces 1132E


题意:

给 定 一 个 容 量 为 W 的 背 包 , 给 定 体 积 为 1 — 8 的 八 个 物 体 的 数 量 。 问 最 大 能 装 下 物 品 的 体 积 。 给定一个容量为W的背包,给定体积为1—8的八个物体的数量。问最大能装下物品的体积。 W18


题解:

裸 的 多 重 背 包 , 但 由 于 数 据 很 大 , 作 如 下 转 化 。 裸的多重背包,但由于数据很大,作如下转化。
假 设 将 容 量 为 W 的 背 包 分 为 若 干 个 容 量 为 840 ( 1 — 8 的 L C M ) 的 小 背 包 , 假设将容量为W的背包分为若干个容量为840(1—8的LCM)的小背包, W84018LCM
那 么 每 个 物 品 都 能 单 独 装 满 小 背 包 。 那么每个物品都能单独装满小背包。
将 能 凑 成 840 的 物 品 丢 进 背 包 后 , 剩 下 的 物 品 体 积 必 然 小 于 840 ∗ 8 。 将能凑成840的物品丢进背包后,剩下的物品体积必然小于840*8。 8408408
接 下 来 仅 需 对 容 量 为 840 ∗ 8 的 背 包 进 行 处 理 。 接下来仅需对容量为840*8的背包进行处理。 8408

  • d p [ i ] [ j ] = d p [ i ] [ j ] ∣ d p [ i − 1 ] [ j − k ∗ i ] dp[i][j] = dp[i][j]|dp[i-1][j-k*i] dp[i][j]=dp[i][j]dp[i1][jki]

#include <bits\stdc++.h>
using namespace std;
typedef long long ll;
const int N = 8400;
ll cnt[9], pre[9];
ll dp[9][N];

int main() {
    ll W, sum = 0, w = 0, ans = 0;
    cin >> W;
    for(int i = 1 ; i <= 8 ; i++){
        cin >> cnt[i];
        sum += cnt[i]*i;
        pre[i] = min(1LL*840/i, cnt[i]);
        cnt[i] -= pre[i];
        w += min(cnt[i], (max(0LL, W-840)-w)/i)*i;
    }
    if(sum <= W){
        return cout << sum , 0;
    }
    dp[0][0] = 1;
    for(int i = 1 ; i <= 8 ; i++){
        for(int j = 0 ; j <= 840*8 ; j++){
            for(int k = 0 ; k <= min(pre[i], 1LL*j/i) ; k++){
                dp[i][j] = dp[i][j]|dp[i-1][j-k*i];
            }
        }
    }
    for(int j = 0 ; j <= W-w ; j++){
        if(dp[8][j]){
            ans = w+j;
        }
    }
    cout << ans << endl;
    return 0; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值