1 条题解

  • 0
    @ 2025-8-24 21:24:53

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar kkksc03
    洛谷吉祥物 DA✩ZE

    搬运于2025-08-24 21:24:52,当前版本为作者最后更新于2013-08-12 22:35:37,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    By tinylic

    如果没有b[i]这个属性的话就是明显的01背包问题。

    现在考虑相邻的两个物品x,y。假设现在已经耗费p的时间,那么分别列出先做x,y的代价:

    a[x]-(p+c[x])*b[x]+a[y]-(p+c[x]+c[y])*b[y] (①)

    a[y]-(p+c[y])*b[y]+a[x]-(p+c[y]+c[x])*b[x] (②)

    对这两个式子化简,得到①>②的条件是c[x]*b[y]<c[y]*b[x].

    发现只要满足这个条件的物品对(x,y),x在y前的代价永远更优。

    因此可以根据这个条件进行排序,之后就是简单的01背包了。

    
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define LL long long
    #define maxn 100001
    
    using namespace std;
    
    struct node {
        int a, b, c;
    }a[maxn];
    
    LL f[maxn], ans;
    int T, n, i, j;
    
    bool cmp(node a, node b) {
        return (LL)a.c * (LL)b.b < (LL)b.c * (LL)a.b;
    }
    
    int main() {
    
        scanf("%d%d", &T, &n);
        for (i = 0; i < n; i++)
            scanf("%d", &a[i].a);
        for (i = 0; i < n; i++)
            scanf("%d", &a[i].b);
        for (i = 0; i < n; i++)
            scanf("%d", &a[i].c);
        
        sort(a, a + n, cmp);
    
        memset(f, 255, sizeof f);
        f[0] = 0;
    
        for (i = 0; i < n; i++) {
            for (j = T; j >= 0; --j)
                if (f[j] != -1 && j + a[i].c <= T)
                    f[j + a[i].c] = max(f[j + a[i].c], f[j] + (LL)a[i].a - (LL)(j + a[i].c) * (LL)a[i].b);
        }
        for (i = 0; i <= T; i++)
            ans = max(ans, f[i]);
        cout << ans << endl;
    }
    
    
    
    • 1

    信息

    ID
    411
    时间
    1000ms
    内存
    125MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者