• 关于一些背包。。。。


    P06: 分组的背包问题

    问题

    有N件物品和一个容量为V的背包。第i件物品的费用是c,价值是w。这些物品被划分为若干组,每组中的物品互相冲突,最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

    算法

    这个问题变成了每组物品有若干种策略:是选择本组的某一件,还是一件都不选。也就是说设f[k][v]表示前k组物品花费费用v能取得的最大权值,则有:

    f[k][v]=max{f[k-1][v],f[k-1][v-c]+w|物品i属于组k}

    使用一维数组的伪代码如下:

    for 所有的组k for v=V..0 for 所有的i属于组k f[v]=max{f[v],f[v-c]+w}


    #include <iostream>
    #include <cmath>
    using namespace std;

    #define T 2
    #define N 3
    #define V 11

    int main(){
        //初始化物品的价值和占用容积
        int value[T][N] = {{10, 20, 15}, {18, 11, 13}};
        int volume[T][N] = {{4, 7, 6}, {5, 5, 6}};

        //初始化dp用的数组
        int dp[V+1] = {0};

        //dp每步都需要最优化
        for (int i = 0; i < T; i++)
            for (int j = V; j >= 0; j--)
                for (int k =0; k < N; k++)
                    if (j - volume[k] >= 0)
                        dp[j] = max(dp[j], dp[j-volume[k]]+value[k]);

        cout<<dp[V]<<endl;
        system("pause");
    }


    P05: 二维费用的背包问题

    问题

    二维费用的背包问题是指:对于每件物品,具有两种不同的费用;选择这件物品必须同时付出这两种代价;对于每种代价都有一个可付出的最大值(背包容量)。问怎样选择物品可以得到最大的价值。设这两种代价分别为代价1和代价2,第i件物品所需的两种代价分别为a和b。两种代价可付出的最大值(两种背包容量)分别为V和U。物品的价值为w

    算法

    费用加了一维,只需状态也加一维即可。设f[v]表示前i件物品付出两种代价分别为v和u时可获得的最大价值。状态转移方程就是:

    f[v]=max{f[i-1][v],f[i-1][v-a][u-b]+w}

    如前述方法,可以只使用二维的数组:当每件物品只可以取一次时变量v和u采用逆序的循环,当物品有如完全背包问题时采用顺序的循环。当物品有如多重背包问题时拆分物品。这里就不再给出伪代码了,相信有了前面的基础,你能够自己实现出这个问题的程序。

    物品总个数的限制

    有时,“二维费用”的条件是以这样一种隐含的方式给出的:最多只能取M件物品。这事实上相当于每件物品多了一种“件数”的费用,每个物品的件数费用均为1,可以付出的最大件数费用为M。换句话说,设f[v]

    表示付出费用v、最多选m件时可得到的最大价值,则根据物品的类型(01、完全、多重)用不同的方法循环更新,最后在f[0..V][0..M]范围内寻找答案。

    复数域上的背包问题

    另一种看待二维背包问题的思路是:将它看待成复数域上的背包问题。也就是说,背包的容量以及每件物品的费用都是一个复数。而常见的一维背包问题则是实数域上的背包问题。(注意:上面的话其实不严谨,因为事实上我们处理的都只是整数而已。)所以说,一维背包的种种思想方法,往往可以应用于二位背包问题的求解中,因为只是数域扩大了而已。


    #include <iostream>
    #include <cmath>
    using namespace std;
     
    #define K 5
    #define V 18
    #define C 15
     
    int main(){
        //初始化物品的价值,占用容积,花销
        int value[K] = {10, 20, 15, 18, 11};
        int volume[K] = {4, 7, 6, 5, 5};
        int cost[K] = {5, 6, 5, 5, 4};
     
        //初始化dp用的数组
        int dp[V+1][C+1] = {0};
     
        //dp每步都需要最优化
        for (int i = 0; i < K; i++)
            for (int j = V; j >= volume; j--)
                for (int k = C; k >= cost; k--)
                    dp[j][k] = max(dp[j][k], dp[j-volume][k-cost]+value);
     
        cout<<dp[V][C]<<endl;
        system("pause");

    }


     
     第K大背包

     for(i=1;i<=n;i++)
        {
            for(j=V;j>=cost;j--)
            {
                for(tt=1;tt<=K;tt++)
                {
                    d[tt]=f[j][tt];
                    p[tt]=f[j-cost][tt]+weight;
                }

                d[tt]=-1;
                p[tt]=-1;

                int x,y,z;
                x=y=z=1;

                while(z<=K&&(x<=K||y<=K))
                {
                    if(d[x]>p[y])
                        f[j][z]=d[x++];
                    else
                        f[j][z]=p[y++];
                    if(f[j][z]!=f[j][z-1])
                        z++;
                }

            }
        }
  • 相关阅读:
    Photoshop 更改图片颜色
    搜索引擎优化网页设计:最佳实践
    Cocos2d-x 精灵碰撞检測(方法一)
    JS 计算2个日期相差的天数
    《Java并发编程实战》第七章 取消与关闭 读书笔记
    LeetCode_3Sum
    Pascal Hexagrammum Mysticum 的深度探索
    HDU 5274 Dylans loves tree(LCA+dfs时间戳+成段更新 OR 树链剖分+单点更新)
    高速查询hive数据仓库表中的总条数
    cocos2d-x触摸事件优先级
  • 原文地址:https://www.cnblogs.com/CKboss/p/3350950.html
Copyright © 2020-2023  润新知