关于一些背包。。。。

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++;
            }

        }
    }
posted @ 2013-07-23 05:18  码代码的猿猿  阅读(184)  评论(0)    收藏  举报