• 完全背包


    转自:(http://blog.csdn.net/wumuzi520/article/details/7014830)
    完全背包是在N种物品中选取若干件(同一种物品可多次选取)放在空间为V的背包里,每种物品的体积为C1,C2,…,Cn,与之相对应的价值为W1,W2,…,Wn.求解怎么装物品可使背包里物品总价值最大。
    动态规划(DP):
    1) 子问题定义:F[i][j]表示前i种物品中选取若干件物品放入剩余空间为j的背包中所能得到的最大价值。
    2) 根据第i种物品放多少件进行决策
    (2-1)
    其中F[i-1][j-K*C[i]]+K*W[i]表示前i-1种物品中选取若干件物品放入剩余空间为j-K*C[i]的背包中所能得到的最大价值加上k件第i种物品;
    设物品种数为N,背包容量为V,第i种物品体积为C[i],第i种物品价值为W[i]。

    f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0<=k*c[i]<=v}

    举例:表2-1为一个背包问题数据表,设背包容量为10根据上述解决方法可得到对应的F[i][j]如表2-2所示,最大价值即为F[6][10].

    2-1背包问题数据表
    物号i 1   2   3   4   5   6
    体积C 3   2   5   1   6   4
    价值W 6   5   10  2   16  82-2i件物品选若干件放入空间为j的背包中得到的最大价值表
        0   1   2   3   4   5   6   7   8   9   10
    0   0   0   0   0   0   0   0   0   0   0   0
    1   0   0   0   6   6   6   12  12  12  18  18
    2   0   0   5   6   10  11  15  16  20  21  25
    3   0   0   5   6   10  11  15  16  20  21  25
    4   0   2   5   7   10  12  15  17  20  22  25
    5   0   2   5   7   10  12  16  18  21  23  26
    6   0   2   5   7   10  12  16  18  21  23  26

    解释1 具体背包中放入那些物品的求法和01背包情况差不多,从F[N][V]逆着走向F[0][0],设i=N,j=V,如果F[i][j]==F[i][j-C[i]]+W[i]说明包里面有第i件物品,同时j -= C[i]。完全背包问题在处理i自减和01背包不同,01背包是不管F[i][j]与F[i-1][j-C[i]]+W[i]相不相等i都要减1,因为01背包的第i件物品要么放要么不放,不管放还是不放其已经遍历过了,需要继续往下遍历而完全背包只有当F[i][j]与F[i-1][j]相等时i才自减1。因为F[i][j]=F[i-1][j]说明背包里面不会含有i,也就是说对于前i种物品容量为j的背包全部都放入前i-1种物品才能实现价值最大化,或者直白的理解为前i种物品中第i种物品物不美价不廉,直接被筛选掉。

    同样可以转换成一维数组来表示:
    for i=1..N
        for v=0..V
            f[v]=max{f[v],f[v-c[i]]+w[i]}

    顺序

    想必大家看出了和01背包的区别,这里的内循环是顺序的,而01背包是逆序的。
    现在关键的是考虑:为何完全背包可以这么写?
    在次我们先来回忆下,01背包逆序的原因?是为了是max中的两项是前一状态值,这就对了。
    那么这里,我们顺序写,这里的max中的两项当然就是当前状态的值了,为何?
    因为每种背包都是无限的。当我们把i从1到N循环时,f[v]表示容量为v在前i种背包时所得的价值,这里我们要添加的不是前一个背包,而是当前背包。所以我们要考虑的当然是当前状态。
    这里同样给大家一道题目:(http://acm.hdu.edu.cn/showproblem.php?pid=1114)
    思路:多重背包和以上两种的不同点在于,多重背包给了具体的重量,价钱,数量,可以转换为01背包求解(代码1),也可以进行二进制优化,将第i种物品分成若干件物品,其中每件物品有一个系数,这件物品的费用和价值均是原来的费用和价值乘以这个系数。使这些系数分别为 1,2,4,…,2^(k-1),n[i]-2^k+1,且k是满足n[i]-2^k+1>0的最大整数。例如,如果n[i]为13,就将这种 物品分成系数分别为1,2,4,6的四件物品,这种方法有模板(代码2),这样就将第i种物品分成了O(log n[i])种物品,将原问题转化为了复杂度为O(V*Σlog n[i])的01背包问题,是很大的改进,还有楼天城的单调队列法,表示不会。。。

    代码
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    #include<string.h>
    #define mem(a,b) memset(a,b,sizeof(a));
    #define INF 0x3fffffff
    int v[50005],w[10005];
    int f[10005];
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            mem(v,0);
            mem(w,0);
            mem(f,0);
            int E,F;
            scanf("%d%d",&E,&F);
            int c=F-E;
            for(int i=1; i<=c; i++)
            {
                f[i]=INF;
            }
            int u;
            scanf("%d",&u);
            for(int i=1; i<=u; i++)
            {
                int n,m;
                scanf("%d%d",&n,&m);
                v[i]=n;
                w[i]=m;
            }
            for(int i=1; i<=u; i++)
            {
                for(int j=w[i]; j<=c; j++)
                {
                    f[j]=min(f[j],f[j-w[i]]+v[i]);
                }
            }
            if(f[c]==INF)
                printf("This is impossible.
    ");
            else
                printf("The minimum amount of money in the piggy-bank is %d.
    ",f[c]);
        }
        return 0;
    }

    因为三个背包加在一起太长,我都看不下去了,换个地方,
    01背包:http://blog.csdn.net/zxy160/article/details/54378762
    多重背包:http://blog.csdn.net/zxy160/article/details/54410915

    "No regrets."
  • 相关阅读:
    青石巷-仰天长笑出门去 七班岂是蓬嵩人
    D语言-变量、输入、输出、注释
    D语言-认识D语言&安装
    D语言-随机数游戏
    全网一定不是最好懂的C++线性筛素数
    【玩转SpringBoot】异步任务执行与其线程池配置
    【玩转SpringBoot】通过事件机制参与SpringBoot应用的启动过程
    【玩转SpringBoot】SpringBoot应用的启动过程一览表
    【玩转SpringBoot】让错误处理重新由web服务器接管
    【玩转SpringBoot】翻身做主人,一统web服务器
  • 原文地址:https://www.cnblogs.com/zxy160/p/7215174.html
Copyright © 2020-2023  润新知