O(V*n)的多重背包问题
多重背包问题:
有n件物品,第i件价值为wi,质量为vi,有c1件,问,给定容量V,求获得的最大价值。
朴素做法:
视为0,1,2,...,k种物品的分组背包 [每组只能选一个]
f[i][j]=Max(f[i][j-k*v[i]]+k*w[i])
但是i,j,k都要枚举,复杂度为 n*V*k
朴素做法的改进:
因为发现用二进制可以表示1..k之内的所有数 [整数二进制打开后为01串,所以可以被二进制表示]
所以将k个物品拆分成1,2,4...2^m,k-2^m ( 其中2^m<=k<2^(m+1) ) 这些物品,然后变成01背包问题。
但是n的数目增多了,复杂度为 n*V*logk
利用单调队列的改进:
1.我们可以发现每个容量都能表示成 v*x+d 的形式[ v表示当前考虑的物品的容量 ]
2.在上一点的启发下,我们发现一个f[v*x+d]在考虑当前物品时,只能由f[v*y+d]转移而来。 [其中x-y<=k]。
也就是说,对v取模的余数相同的容量之间才能互相转移,而且要求x-y<=k。又因为求的是最大值的转移,所以满足单调队列的适用性。
于是乎,我们对于余数d相同的容量分别建一个单调队列,然后枚举x f[x*v+d],进行转移即可。
#include<cstdio>
#include<cstring> inline int in(){
int x=,flag=;char ch=getchar();
while(ch!='-' && (ch>'' || ch<'')) ch=getchar();
if(ch=='-') flag=-,ch=getchar();
while(ch>='' && ch<='') x=x*+ch-'',ch=getchar();
return x*flag;
} int a[],b[],f[];
int w,v,k,n,V,l,r; void insert(int x,int y){
while(l<=r && b[r]<=y) r--;
a[++r]=x; b[r]=y;
} inline int Max(int a,int b){
if(a>b) return a;return b;
} int main(){
n=in(),V=in();
int Lim;
for(int i=;i<=n;i++){
v=in();w=in();k=in();
if(k==){
for(int j=V;j>=v;j--)
f[j]=Max(f[j],f[j-v]+w);
continue;
}
else if(k<){
for(int j=v;j<=V;j++)
f[j]=Max(f[j],f[j-v]+w);
continue;
}
if(V/v<k) k=V/v;
for(int d=;d<v;d++){
l=,r=;Lim=(V-d)/v;
for(int x=;x<=Lim;x++){
insert(x,f[x*v+d]-x*w);
if(a[l]<x-k) l++;
f[x*v+d]=b[l]+x*w;
}
}
}
printf("%d",f[V]);
return ;
}
codevs 3269 混合背包
AC通道:http://codevs.cn/problem/3269/
O(V*n)的多重背包问题的更多相关文章
- 多重背包问题:悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(HDU 2191)(二进制优化)
悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 HDU 2191 一道裸的多重背包问题: #include<iostream> #include<algorithm> #i ...
- 多重背包问题的两种O(M*N)解法
多重背包的题目很多,最著名的是poj1742楼教主的男人八题之一. poj1742:coins 有几种面值的钱币和每种的数量,问能够组成m以内的多少种钱数 这个题大家都归为多重背包问题,不过跟实际意义 ...
- 5. 多重背包问题 II 【用二进制优化】
多重背包问题 II 描述 有 NN 种物品和一个容量是 VV 的背包. 第 ii 种物品最多有 sisi 件,每件体积是 vivi,价值是 wiwi. 求解将哪些物品装入背包,可使物品体积总和不超过背 ...
- 4. 多重背包问题 I
多重背包问题 I 描述 有 NN 种物品和一个容量是 VV 的背包. 第 ii 种物品最多有 sisi 件,每件体积是 vivi,价值是 wiwi. 求解将哪些物品装入背包,可使物品体积总和不超过背包 ...
- 51nod 多重背包问题(动态规划)
多重背包问题 一个背包,承量有限为W,有n种物体,第i种物体,价值Vi,占用重量为 Wi,且有Ci件,选择物品若干放入背包,使得总重量不超过背包的承重.总价值最大? 输入 第1行,2个整数,N和W中间 ...
- C语言-多重背包问题
多重背包问题 问题:有N种物品和一个容量为V的背包.第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大. 分 ...
- 多重背包问题II
多重背包问题II 总体积是m,每个小物品的体积是A[i] ,每个小物品的数量是B[i],每个小物品的价值是C[i] 求能够放入背包内的最大物品能够获得的最大价值 和上一个很类似 上一题体积就是价值,这 ...
- 【动态规划/多重背包问题】POJ1014-Dividing
多重背包问题的优化版来做,详见之前的动态规划读书笔记. dp[i][j]表示前i中数加得到j时第i种数最多剩余几个(不能加和得到i的情况下为-1)递推式为: dp[i][j]=mi(dp[i-1][j ...
- poj 1742 多重背包问题 dp算法
题意:硬币分别有 A1.....An种,每种各有C1......Cn个,问组成小于m的有多少种 思路:多重背包问题 dp[i][j]表示用前i种硬币组成j最多剩下多少个 dp=-1的表示凑不齐 dp ...
随机推荐
- Outlook 2007无法打开链接"由于本机的限制 该操作已被取消"
编写人:CC阿爸 2014-2-17 近来在日常维护中,经常性的遇到用户在outlook中打开链接,提示[由于本机的限制,该操作已被取消],第一次的在网上搜索到解决办法后, 第二次再处理时,又没能记住 ...
- 使用DBCP时发生AbstractMethodError异常
使用DBCP时发生AbstractMethodError异常,错误描述: Exception in thread "main" java.lang.AbstractMethodEr ...
- PHP MYSQLI中事务处理
MYSQL事务处理让所有sql语句执行成功后才去处理,如果有一条没有成功或者报错就会回滚事务,防止敏感操作处理失败.MYSQL中只有INNODB和BDB类型的数据表才能支持事务处理!其它类型是不支持的 ...
- Java transient volatile关键字(转)
Volatile修饰的成员变量在每次被线程访问时,都强迫从主内存中重读该成员变量的值.而且,当成员变量发生变化时,强迫线程将变化值回写到主内存.这样在任何时刻,两个不同的线程总是看到某个成员变量的同一 ...
- Java找出所有的水仙花数并输出
水仙花数是三位数,它的各位数字的立方和等于这个三位数本身,例如:371=33+73+13,371就是一个水仙花数. 要判断是否是水仙花数,首先得得到它的每一位上的数.个位数即为对10取余:十位数为对1 ...
- Firebird 修改表名
UPDATE RDB$RELATIONS SET RDB$RELATION_NAME='NEWNAME' where RDB$RELATION_NAME='OLDNAME'; UPDATE RDB$ ...
- 从客户端检测到有潜在危险的Request.Form 值【转】
asp.net开发中,经常遇到“从客户端检测到有潜在危险的Request.Form 值”错误提示,很多人给出的解决方案是: 1.web.config文档<system.web>后面加入这一 ...
- ok6410串口裸机总结
1.串口角色:(1)数据传输通道(2)控制台 2.通讯参数(1)波特率:衡量传输速率的快慢,每秒钟传输数据的位数(bit)(2)数据位:有效数据(3)起始位:线路空闲的时候是高电平,当检测到低电平认为 ...
- Linux下使用Magent+Memcached缓存服务器集群部署
1.编译安装libevent cd /root/soft_hhf/ wget http://cloud.github.com/downloads/libevent/libevent/libeven ...
- swift学习初步(三)--控制流操作
在上一篇博客里面,我谈到了swift里面的一些基本类型以及相关的操作,相信你看了之后一定会觉得其实swift也不难嘛.好吧,这篇博客里面要谈的一些高级操作,可能会让你有点头疼了. 好了,废话不多说了, ...