cf366 C. Dima and Salad(01背包变式)

题意:

n 个物品,每个物品有属性 \(a_i,b_i\)。选择若干物品,要求所选物品 \(\frac {\sum a_i}{\sum b_i}=k\) ,并且最大化 \(\sum a_i\) ,输出最大值。

$1\le n,a_i,b_i\le 100, 1\le k\le 10, $ 都是整数

思路:

限制条件化为 \(\sum (a_i-kb_i)=0\)

就是01背包,物品体积为 \(c_i=a_i-kb_i\),价值为 \(a_i\)

要求所选物品的体积和为0,背包容量 \(1e4\)

初始化 \(f(0)=0\),其他为负无穷

物品体积可能为负,可以加个1000。也可以用 \(f,g\) 分别处理正的体积和负的体积

const int N = 110, C = 1e4;
int n, k, a[N], b[N];
int f[C + 3], g[C + 3]; //要开到最大容量

signed main()
{
    cin >> n >> k;
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 1; i <= n; i++) cin >> b[i];

    memset(f, -INF, sizeof f), f[0] = 0;
    memset(g, -INF, sizeof g), g[0] = 0;

    for(int i = 1; i <= n; i++)
    {
        int c = a[i] - k * b[i];

        if(c >= 0) //正的体积
            for(int j = C; j >= c; j--)
                f[j] = max(f[j], f[j-c] + a[i]);
        else //负的
            for(int j = C; j >= -c; j--)
                g[j] = max(g[j], g[j+c] + a[i]);
    }

    int ans = 0;
    for(int i = 0; i <= C; i++)
        ans = max(ans, f[i] + g[i]);

    cout << (ans ? ans : -1);
}

posted @ 2022-02-09 14:12  Bellala  阅读(32)  评论(0)    收藏  举报