背包3

Time Limit: 2000/1000ms (Java/Others)

Problem Description:

有n种(每一种有无数个)重量和价值分别为Wi,Vi的物品,现从这些物品中挑选出总量不超过W的物品,求所有方案中价值总和的最大值。

Input:

输入包含多组测试用例,每一例的开头为两位整数 n、W(1<=n<=10000,1<=W<=1000),接下来有 n 行,每一行有两位整数 Wi、Vi(1<=Wi<=10000,1<=Vi<=100)

Output:

输出为一行,即所有方案中价值总和的最大值。

Sample Input:

3 4
1 2
2 5
3 7
3 5
2 3
3 4
4 5

Sample Output:

10
7
解题思路:简单的完全背包。和01背包一样,dp[i][j]表示从前i种物品中挑选总重量不超过j时总价值的最大值。
易得状态转移方程:dp[i,j]=max(dp[i-1,j-k*wi]+k*vi)(0<=k*wi<=W),其中dp[i-1,j-k*wi]+k*vi表示前i-1种物品中选取若干件物品放入剩余容量为j-k*wi的背包中所能得到的最大价值加上k件第i种物品。很明显,多了一个参数k,时间复杂度变为O(nW∑(W/wi)),可知这样的时间复杂度是很大的,我们必须找到更优的办法。
因为在dp[i,j]的计算中选择k(k>=1)个物品得到的最大价值与在dp[i][j-wi](背包中已包含至少一件第i种物品)的计算中选择k-1个物品得到的最大价值是相同的,所以dp[i][j]的递推中k>=1部分的计算已经在dp[i][j-wi]的计算中完成了。那么有如下推导过程:
dp[i,j-wi]=max(dp[i-1,j],dp[i-1,(j-wi)-(k-1)*wi]+(k-1)*vi)(k>=1,dp[i-1,j]表示第i种物品一件都不选)
=max(dp[i-1,j],dp[i-1,j-k*wi]+(k-1)*vi)(k>=1,表示当前背包中至少含有一件第i种物品)
dp[i,j]=max(dp[i-1,j],dp[i-1,j-k*wi]+k*vi)(k>=1)
    =max(dp[i-1,j],dp[i,j-wi]+vi)
于是成功地把参数k给消掉了,现在的时间复杂度和01背包一样都为O(nW)。
怎么理解上面的状态转移方程呢?①如果第i件物品一件都不取,显然dp[i,j]=dp[i-1,j];②如果要取,那么当前背包中至少已含有一件第i种物品(即j至少已含有一个wi),则dp[i,j]=dp[i,j-wi]+vi。因为01背包中每个物品只有一件,在放入第i件物品时需考虑到前i-1件物品放入剩余背包容量为j-wi得到的最大价值,但是现在每个物品拥有无限件,即无需考虑前i-1个物品了,所要考虑的就是当前容量下能否再放入一件第i种物品,而dp[i,j-wi]已确保dp[i,j]中至少有一件第i种物品,所以要预留wi的背包容量再来存放一件第i种物品,这样就实现了一个物品可以取多件的操作。
同样地,完全背包空间也可以优化到O(W)。怎么实现呢?只需将01背包第二重循环正序枚举即可。为什么呢?通过模拟过程可以发现,正序使得一个物品可以被取多次。因为01背包中按照W递减来循环是为了保证第i次循环中的状态dp[i,j]是由状态dp[i-1,j-wi]递推而来,换句话说,这正是为了保证每件物品只选一次,保证在考虑“选入第i件物品”这件策略时,依据的是一个绝无已经选入第i件物品的子结果dp[i−1,j−wi]。而现在完全背包的特点恰是每种物品可选无限件,所以在考虑“加选一件第i种物品”这种策略时,却正需要一个可能已选入第i种物品的子结果dp[i,j-wi],所以就可以并且必须采用wi~W递增的顺序循环。
一维滚动数组状态转移方程:dp[j]=max(dp[j],dp[j-w[i]]+v[i])。
AC代码一:(二维数组实现)
 #include<bits/stdc++.h>
using namespace std;
int n,W,v[],w[],dp[][];
int main(){
while(cin>>n>>W){
for(int i=;i<=n;++i)cin>>w[i]>>v[i];
memset(dp,,sizeof(dp));
for(int i=;i<=n;++i){
for(int j=;j<=W;++j){
if(j<w[i])dp[i][j]=dp[i-][j];//当前容量j容纳不下一件第i种物品
else dp[i][j]=max(dp[i-][j],dp[i][j-w[i]]+v[i]);//再拿一件第i种物品和一件都不拿的情况比一下
}
}
cout<<dp[n][W]<<endl;
}
return ;
}
AC代码二:(一维数组实现)
 #include<bits/stdc++.h>
using namespace std;
int n,W,v[],w[],dp[];
int main(){
while(cin>>n>>W){
for(int i=;i<n;i++)
cin>>w[i]>>v[i];
memset(dp,,sizeof(dp));
for(int i=;i<n;++i) //种类
for(int j=w[i];j<=W;++j) //重量从小到大枚举
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
cout<<dp[W]<<endl;
}
return ;
}

ACM_完全背包的更多相关文章

  1. ACM_物品分堆(01背包)

    物品分堆 Time Limit: 2000/1000ms (Java/Others) Problem Description: 有n个物品,物品i的重量为Wi,现在想要把这个n个物品分类两堆,求最小的 ...

  2. ACM_寒冰王座(完全背包)

    寒冰王座 Time Limit: 2000/1000ms (Java/Others) Problem Description: 不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票(记住,只有一张钞票) ...

  3. nyist oj 311 全然背包 (动态规划经典题)

    全然背包 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描写叙述 直接说题意,全然背包定义有N种物品和一个容量为V的背包.每种物品都有无限件可用.第i种物品的体积是c,价值是 ...

  4. NYOJ 311 完全背包

    完全背包 时间限制:3000 ms  |  内存限制:65535 KB 难度:4   描述 直接说题意,完全背包定义有N种物品和一个容量为V的背包,每种物品都有无限件可用.第i种物品的体积是c,价值是 ...

  5. 【USACO 3.1】Stamps (完全背包)

    题意:给你n种价值不同的邮票,最大的不超过10000元,一次最多贴k张,求1到多少都能被表示出来?n≤50,k≤200. 题解:dp[i]表示i元最少可以用几张邮票表示,那么对于价值a的邮票,可以推出 ...

  6. HDU 3535 AreYouBusy (混合背包)

    题意:给你n组物品和自己有的价值s,每组有l个物品和有一种类型: 0:此组中最少选择一个 1:此组中最多选择一个 2:此组随便选 每种物品有两个值:是需要价值ci,可获得乐趣gi 问在满足条件的情况下 ...

  7. HDU2159 二维完全背包

    FATE Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  8. CF2.D 并查集+背包

    D. Arpa's weak amphitheater and Mehrdad's valuable Hoses time limit per test 1 second memory limit p ...

  9. UVALive 4870 Roller Coaster --01背包

    题意:过山车有n个区域,一个人有两个值F,D,在每个区域有两种选择: 1.睁眼: F += f[i], D += d[i] 2.闭眼: F = F ,     D -= K 问在D小于等于一定限度的时 ...

随机推荐

  1. msp430入门编程03

    msp430的C标识符和关键字 msp430入门学习 msp430入门编程

  2. Python基础之 一 字典(dict)

    字典:是一种key - value的数据类型.语法:info = { key:value }特性:无序,key必须唯一(所以天生去重) 方法如下:del dict[key]:删除字典指定键len(di ...

  3. Codeforces Round #343 (Div. 2)【A,B水题】

    A. Far Relative's Birthday Cake 题意: 求在同一行.同一列的巧克力对数. 分析: 水题~样例搞明白再下笔! 代码: #include<iostream> u ...

  4. SAS编程基础 - 逻辑库和数据集

    1. SAS逻辑库 1.1 创建SAS逻辑库: libname lb 'F:\Data_Model'; libname是关键字,lb是创建的逻辑库的名称,引号内的内容是目录路径,最后一个分号结束程序语 ...

  5. mvn打包源码的方法:maven-source-plugin

    maven-javadoc-plugin可以打包 dubbo-demo-provider-2.6.1-javadoc.jar maven-jar-plugin 打包插件 dubbo-demo-prov ...

  6. 采用jmeter测试dubbo服务接口

    http://www.kissyu.org/2017/02/08/jmeter%E6%B5%8B%E8%AF%95dubbo%E6%8E%A5%E5%8F%A3/

  7. react 项目实战(六)提取布局组件

    重复代码是混乱的根源!,本篇文章我们来继续消灭重复代码. 目标 细心的同学应该能发现:每一个Page组件(/src/pages下的组件)的render方法都拥有相似的jsx结构,比如: render ...

  8. 开放-封闭"原则(OCP)

    Open-Closed Principle原则讲的是:一个软件实体应当对扩展开放,对修改关闭. 优点: 通过扩展已有软件系统,可以提供新的行为,以满足对软件的新的需求,使变化中的软件有一定的适应性和灵 ...

  9. ZOJ 3870 Team Formation 贪心二进制

                                                    B - Team Formation Description For an upcoming progr ...

  10. projecteuler----&gt;problem=12----Highly divisible triangular number

    title: The sequence of triangle numbers is generated by adding the natural numbers. So the 7th trian ...