ACM_完全背包
背包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_完全背包的更多相关文章
- ACM_物品分堆(01背包)
物品分堆 Time Limit: 2000/1000ms (Java/Others) Problem Description: 有n个物品,物品i的重量为Wi,现在想要把这个n个物品分类两堆,求最小的 ...
- ACM_寒冰王座(完全背包)
寒冰王座 Time Limit: 2000/1000ms (Java/Others) Problem Description: 不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票(记住,只有一张钞票) ...
- nyist oj 311 全然背包 (动态规划经典题)
全然背包 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描写叙述 直接说题意,全然背包定义有N种物品和一个容量为V的背包.每种物品都有无限件可用.第i种物品的体积是c,价值是 ...
- NYOJ 311 完全背包
完全背包 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 直接说题意,完全背包定义有N种物品和一个容量为V的背包,每种物品都有无限件可用.第i种物品的体积是c,价值是 ...
- 【USACO 3.1】Stamps (完全背包)
题意:给你n种价值不同的邮票,最大的不超过10000元,一次最多贴k张,求1到多少都能被表示出来?n≤50,k≤200. 题解:dp[i]表示i元最少可以用几张邮票表示,那么对于价值a的邮票,可以推出 ...
- HDU 3535 AreYouBusy (混合背包)
题意:给你n组物品和自己有的价值s,每组有l个物品和有一种类型: 0:此组中最少选择一个 1:此组中最多选择一个 2:此组随便选 每种物品有两个值:是需要价值ci,可获得乐趣gi 问在满足条件的情况下 ...
- HDU2159 二维完全背包
FATE Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- CF2.D 并查集+背包
D. Arpa's weak amphitheater and Mehrdad's valuable Hoses time limit per test 1 second memory limit p ...
- UVALive 4870 Roller Coaster --01背包
题意:过山车有n个区域,一个人有两个值F,D,在每个区域有两种选择: 1.睁眼: F += f[i], D += d[i] 2.闭眼: F = F , D -= K 问在D小于等于一定限度的时 ...
随机推荐
- POJ 3468_A Simple Problem with Integers(树状数组)
完全不知道该怎么用,看书稍微懂了点. 题意: 给定序列及操作,求区间和. 分析: 树状数组可以高效的求出连续一段元素之和或更新单个元素的值.但是无法高效的给某一个区间的所有元素同时加个值. 不能直接用 ...
- 洛谷 P1166 打保龄球
P1166 打保龄球 题目描述 打保龄球是用一个滚球去打击十个站立的柱,将柱击倒.一局分十轮,每轮可滚球一次或多次,以击倒的柱数为依据计分.一局得分为十轮得分之和,而每轮的得分不仅与本轮滚球情况有关, ...
- Hive之侧视图(Lateral View)
Lateral View和UDTF类功能函数一起使用,表中的每一行和UDTF函数输出的每一行进行连接,生成一张新的虚拟表,可以对UDTF产生的记录设置字段名称,新加的字段可以使用在sort by,gr ...
- cn_windows_10_multiple_editions_version_1607_updated_jul_2016_x64
ed2k://|file|cn_windows_10_multiple_editions_version_1607_updated_jul_2016_x64_dvd_9056935.iso|43471 ...
- MongoDB小结15 - find【查询条件$ne】
$ne表示不相等 db.user.find({"name":{"$ne":"william"}})
- 扩展GCD 中国剩余定理(CRT) 乘法逆元模版
extend_gcd: 已知 a,b (a>=0,b>=0) 求一组解 (x,y) 使得 (x,y)满足 gcd(a,b) = ax+by 以下代码中d = gcd(a,b).顺便求出gc ...
- android插件化-apkplug从宿主启动插件Activity-06
插件是一个apk文件它存在自己的Activity界面和UI显示,本节将解说如何配置插件的启动Activity以及如何从宿主启动它. 一 配置插件apk的对外启动Activity (内部activity ...
- 利用runtime检測这个对象是否存在某属性?
假定有实例对象-instance,我们怎样知道该实例对象是否存在属性-propertyName? 利用runtime,我们能够获取到它的属性列表 1)属性列表 unsigned int outCoun ...
- 【bzoj1029】[JSOI2007]建筑抢修
按照t2从小到大排列之后贪心. 若当前任务可以插入,则插入. 若当前任务不可以插入,分两种情况: ①当前任务的耗时大于等于之前插入的任务的最大耗时:跳过当前任务 ②当前任务的耗时小于之前插入的任务的耗 ...
- jvm实例的个数
Generally speaking, each application will get its own JVM instance and its own OS-level process and ...