多重背包问题 II(Acwing 5,二进制优化多重背包 + 单调队列优化多重背包)

一.题目链接:

多重背包问题 II

二.题目大意:

多重背包

三.分析:

做个笔记,偷笑.

大佬的具体分析

立下 flag:这次我要学好 DP!!!

四.代码实现:

二进制优化

#include <bits/stdc++.h>
using namespace std;

const int M = (int)2e3;

int dp[M + 5];

struct node
{
    int v, w;
};
vector <node> vec;

int main()
{
    int n, m;
    cin >> n >> m;
    for(int i = 1, v, w, s; i <= n; ++i)
    {
        cin >> v >> w >> s;
        for(int j = 1; s >= j; j<<= 1)
        {
            s -= j;
            vec.push_back({v * j, w * j});
        }
        if(s)   vec.push_back({v * s, w * s});
    }
    
    for(auto i: vec)
    {
        for(int j = m; j >= i.v; --j)
        {
            dp[j] = max(dp[j], dp[j - i.v] + i.w);
        }
    }
    cout << dp[m] << "\n";
    
    return 0;
}

单调队列优化

#include <bits/stdc++.h>
using namespace std;

const int M = (int)2e4;
const int inf = 0x3f3f3f3f;

int q[M + 5];
int dp[M + 5];

int cal(int u, int k, int v, int w)
{
    return dp[u + k * v] - k * w;
}

int main()
{
    int n, m;
    scanf("%d %d", &n, &m);
    memset(dp, -inf, sizeof(dp));
    dp[0] = 0;
    for(int i = 1, v, w, c; i <= n; ++i)
    {
        scanf("%d %d %d", &v, &w, &c);
        for(int u = 0; u < v; ++u)
        {
            int l = 1, r = 0;
            int mx = (m - u) / v;
            for(int k = mx - 1; k >= max(mx - c, 0); --k)
            {
                while(l <= r && cal(u, k, v, w) >= cal(u, q[r], v, w))   --r;
                q[++r] = k;
            }
            for(int p = mx; p >= 0; --p)
            {
                while(l <= r && q[l] > p - 1)   ++l;
                if(l <= r)  dp[u + p * v] = max(dp[u + p * v], p * w + cal(u, q[l], v, w));
                if(p - 1 - c >= 0)
                {
                    while(l <= r && cal(u, p - 1 - c, v, w) >= cal(u, q[r], v, w))  --r;
                    q[++r] = p - 1 - c;
                }
            }
        }
    }
    int ans = 0;
    for(int i = 1; i <= m; ++i) ans = max(ans, dp[i]);
    printf("%d\n", ans);
    return 0;
}

 

很抱歉,由于我是一名语言模型AI,我并不具备直接运行代码的能力。但是,我可以为您提供一些关于多重背包二进制优化输入c代码的信息和建议。 多重背包问题是一种经典的动态规划问题,二进制优化是对传统多重背包算法的一种优化手段,可以大幅提升算法性能。 以下是一个可能的多重背包二进制优化输入c代码的基本框架: ```c #include <stdio.h> #define MAXN 1005 int N; // 物品数量 int W; // 背包总容量 int w[MAXN]; // 每个物品的重量 int v[MAXN]; // 每个物品的价值 int f[MAXN][MAXN]; int max(int a, int b) { return a > b ? a : b; } int main() { scanf("%d %d", &N, &W); for (int i = 1; i <= N; i++) { scanf("%d %d", &w[i], &v[i]); } // 以下为二进制优化部分 int n = 1; for (int i = 1; i <= N; i++) { int k = 1; while (k <= v[i]) { w[n] = k * w[i]; v[n++] = k * v[i]; v[i] -= k; k *= 2; } if (v[i] > 0) { w[n] = v[i] * w[i]; v[n++] = v[i] * v[i]; } } N = n - 1; // 多重背包部分 for (int i = 1; i <= N; i++) { for (int j = W; j >= w[i]; j--) { for (int k = 1; k * w[i] <= j; k++) { f[j] = max(f[j], f[j - k * w[i]] + k * v[i]); } } } printf("%d\n", f[W]); return 0; } ``` 以上代码实现了基于二进制优化多重背包问题,通过对每个物品按其价值进行二进制拆分,并将其转化为多个物品,以便于后续的多重背包求解。 需要注意的是,该算法的时间复杂度为 $O(NV\log V)$,其中 $V$ 为所有物品的总价值。如果您需要更高效的算法实现,可以尝试其他优化技巧,如单调队列优化、有界背包优化等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值