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 ...
随机推荐
- Silverlight - GPU加速
1. 在Silverlight plug-in上设置 <param name="enableGPUAcceleration" value="true" / ...
- PHP计算某个目录大小的方法
用PHP来计算某个目录大小的方法. PHP CURL session COOKIE 可以调用系统命令,还可以这样: <?php function dirsize($dir) { @$dh ...
- sql分类及基本sql操作,校对规则(mysql学习笔记二)
sql针对操作对象分为不同语言 数据操作(管理)语言 DML或者将其细分为 ( 查询 DQL 管理(增,删,改) DML) 数据定义语言(对保存数据的格式进行定义) DDL 数据库控制语言(针对数 ...
- php中关于抽象(abstract)类和抽象方法的问题解析
在面向对象(OOP)语言中,一个类可以有一个或多个子类,而每个类都有至少一个公有方法作为外部代码访问的接口.而抽象方法就是为了方便继承而引入的,现在来看一下抽象类和抽象方法分别是如何定义以及他们的特点 ...
- MySQL性能优化笔记整理
一.测试篇 1.测试目的,就是量化找出短板(基础参数配置) 2.测试三大指标 IOPS:每秒处理的IO请求数,即IO响应速度(注意和IO吞吐量的区别) QPS:每秒请求(查询)次数 TPS:每秒事务数 ...
- Hashset,Iterator
HashSet类主要是设计用来做高性能集运算的,例如对两个集合求交集.并集.差集等.集合中包含一组不重复出现且无特性顺序的元素. (一)HashSet的一些特性如下: 1.HashSet中的值不能重复 ...
- 一篇文章教你读懂Makefile
makefile很重要 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professiona ...
- Windows Phone播放视频流
前言 MediaElement是Windows Phone中播放本地或者网络视频文件和音乐文件的常用控件,支持的格式可以从这里看.通过Play,Pause,Stop,Position方法或属性可以方便 ...
- Install sheild设置了Blue皮肤,但是有的窗口更改不了问题
发现和顺序有关系:1.先指定skins:2.Release:3.再改对话框
- MVC返回图片
这几天忙着一些小事,也没有写什么了,今天,我们来玩一个比较简单的东东.就是在MVC下如何返回图片,相信,在传统WebForm下,大家都晓得怎么弄,方也不限于一种,但是,在架构较为严格的MVC里面,刚开 ...