• 背包


    01背包

    最大价值

    背包数量为 \(V\),有 \(n\)件物品,重量为 \(w_i\),价值为 \(c_i\)。求能获得最大价值。

    ll V, n, w[10000], c[10000], f[10000];
    
    int main()
    {
        V = read();
        n = read();
        for (int i = 1; i <= n; ++i)
        {
            w[i] = read();
            c[i] = read();
        }
        for (int i = 1; i <= n; ++i)
            for (int v = V; v >= w[i]; --v)
            {
                if (f[v - w[i]] + c[i] > f[v])
                    f[v] = f[v - w[i]] + c[i];
            }
        printf("%lld\n", f[V]);
        return 0;
    }
    

    方案数

    一种物品只能选一次,组合出固定价值的方案数问题。

    例题:ybt1291:数字组合

    ll a[21], f[1003], n, t;
    int main()
    {
        n = read();
        t = read();
        for (int i = 1; i <= n; ++i)
        {
            a[i] = read();
        }
        f[0] = 1;
        for (int i = 1; i <= n; ++i)
        {
            for (int j = t; j >= a[i]; --j)
            {
                f[j] += f[j - a[i]];
            }
        }
        printf("%lld\n", f[t]);
        return 0;
    }
    

    完全背包

    最大价值

    一种物品可以选无限次。
    只需要改一下第二层循环的循环顺序就行了。

    for (int i = 1; i <= n; ++i)
        for (int v = w[i]; v <= V; ++v)
        {
            if (f[v - w[i]] + c[i] > f[v])
                f[v] = f[v - w[i]] + c[i];
        }
    

    方案数

    一种物品可以选无限次,组合出固定价值的方案数问题。
    例题:ybt1293:买书

    ll a[5], f[10002], m;
    
    int main()
    {
        m = read();
        a[1] = 10, a[2] = 20, a[3] = 50, a[4] = 100;
        f[0] = 1;
        for (int i = 1; i <= 4; ++i)
        {
            for (int j = a[i]; j <= m; ++j)
            {
                f[j] += f[j - a[i]];
            }
        }
        printf("%lld\n", f[m]);
        return 0;
    }
    

    混合背包

    一种物品可以选 \(p\) 次。

    ll w[31], c[31], p[31];
    ll f[201], n, m;
    
    int main()
    {
        m = read();
        n = read();
        for (int i = 1; i <= n; ++i)
        {
            w[i] = read();
            c[i] = read();
            p[i] = read();
        }
        for (int i = 1; i <= n; ++i)
        {
            if (p[i] == 0) //完全
            {
                for (int j = w[i]; j <= m; ++j)
                    f[j] = max(f[j], f[j - w[i]] + c[i]);
            }
            else //01和多重
            {
                for (int j = 1; j <= p[i]; ++j)
                {
                    for (int k = m; k >= w[i]; --k)
                    {
                        f[k] = max(f[k], f[k - w[i]] + c[i]);
                    }
                }
            }
        }
        printf("%lld\n", f[m]);
        return 0;
    }
    

    二维费用背包

    再加一重循环,多开一维数组即可。

    例题:ybt1271:【例9.15】潜水员

    ll v, u, k;
    ll a[1091], b[1021], c[1092];
    ll f[101][101];
    
    int main()
    {
        memset(f, 127, sizeof f);
        f[0][0] = 0;
        v = read();
        u = read();
        k = read();
        for (int i = 1; i <= k; ++i)
        {
            a[i] = read();
            b[i] = read();
            c[i] = read();
        }
        for (int i = 1; i <= k; ++i)
        {
            for (int j = v; j >= 0; --j)
            {
                for (int l = u; l >= 0; --l)
                {
                    ll t1 = j + a[i];
                    ll t2 = l + b[i];
                    t1 = min(t1, v);
                    t2 = min(t2, u);
                    f[t1][t2] = min(f[t1][t2], f[j][l] + c[i]);
                }
            }
        }
        printf("%lld\n", f[v][u]);
        return 0;
    }
    
  • 相关阅读:
    《Ubuntu标准教程》学习总结
    Ubuntu下安装VirtualBox并为其添加USB支持
    Eclipse下配置TinyOS开发环境
    Ubuntu下的网络服务
    Ubuntu12.04添加环境变量
    Ubuntu12.04下搭建Java环境
    poj 1066 线段相交
    poj 2653 (线段相交判断)
    poj 2398 (叉积+二分)
    hdu 4883 思维题
  • 原文地址:https://www.cnblogs.com/EdisonBa/p/14948724.html
Copyright © 2020-2023  润新知