完全背包

来源:互联网 发布:淘宝模块代码 编辑:程序博客网 时间:2024/06/05 10:04

                                                                        完全背包

时间限制:3000 ms  |  内存限制:65535 KB
难度:4
描述

直接说题意,完全背包定义有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的体积是c,价值是w。求解将哪些物品装入背包可使这些物品的体积总和不超过背包容量,且价值总和最大。本题要求是背包恰好装满背包时,求出最大价值总和是多少。如果不能恰好装满背包,输出NO

输入
第一行: N 表示有多少组测试数据(N<7)。
接下来每组测试数据的第一行有两个整数M,V。 M表示物品种类的数目,V表示背包的总容量。(0<M<=2000,0<V<=50000)
接下来的M行每行有两个整数c,w分别表示每种物品的重量和价值(0<c<100000,0<w<100000)
输出
对应每组测试数据输出结果(如果能恰好装满背包,输出装满背包时背包内物品的最大价值总和。 如果不能恰好装满背包,输出NO)
样例输入
21 52 22 52 25 1
样例输出
NO1
解题思路: 

还是动态规划的背包问题。每种物品无限用,所以循环从前向后递推。此题要求必须装满,所以初始化时把数组初始化为无穷大,最后用来筛选排除。

阶段是:在前N件物品中,选取若干件物品放入背包中;   状态是:在前N件物品中,选取若干件物品放入所剩空间为W的背包中的所能获得的最大价值;

  决策是:第N件物品放或者不放;   

 由此可以写出动态转移方程:

  我们用f[i,j]表示在前 i 件物品中选择若干件放在所剩空间为 j 的背包里所能获得的最大价值

  f[i,j]=max{f[i-1,j-Wi]+Pi (j>=Wi), f[i-1,j]}                                      <1>

  这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的。所以有必要将它详细解释一下:“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为f[v];如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-c的背包中”,此时能获得的最大价值就是f[v-c]再加上通过放入第i件物品获得的价值w。

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

表2-1背包问题数据表

物品号i123456体积C325164价值W65102168

 

表2-2前i件物品选若干件放入空间为j的背包中得到的最大价值表

 0123456789100000000000001000666121212181820056101115162021253005610111516202125402571012151720222550257101216182123266025710121618212326
#include<stdio.h>#include<iostream>#include<string.h>#include<algorithm>using namespace std;struct node{    int w,v;}a[2020];int dp[50010];int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n,m;        scanf("%d%d",&n,&m);        memset(dp,-10000000,sizeof(dp));//来表示没有填满        dp[0]=0;        for(int i=0;i<n;i++)        {            scanf("%d%d",&a[i].w,&a[i].v);        }        for(int i=0;i<n;i++)        {           for(int j=a[i].w;j<=m;j++)//体积为j,只用前i+1个物体填的时候(不一定填满)的最大值           {                dp[j]=max(dp[j],dp[j-a[i].w]+a[i].v);           }        }        if(dp[m]>=0)        {            printf("%d\n",dp[m]);        }        else        {            printf("NO\n");        }    }}

0 0
原创粉丝点击