多重背包问题:

  有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)的多重背包问题的更多相关文章

  1. 多重背包问题:悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(HDU 2191)(二进制优化)

    悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 HDU 2191 一道裸的多重背包问题: #include<iostream> #include<algorithm> #i ...

  2. 多重背包问题的两种O(M*N)解法

    多重背包的题目很多,最著名的是poj1742楼教主的男人八题之一. poj1742:coins 有几种面值的钱币和每种的数量,问能够组成m以内的多少种钱数 这个题大家都归为多重背包问题,不过跟实际意义 ...

  3. 5. 多重背包问题 II 【用二进制优化】

    多重背包问题 II 描述 有 NN 种物品和一个容量是 VV 的背包. 第 ii 种物品最多有 sisi 件,每件体积是 vivi,价值是 wiwi. 求解将哪些物品装入背包,可使物品体积总和不超过背 ...

  4. 4. 多重背包问题 I

    多重背包问题 I 描述 有 NN 种物品和一个容量是 VV 的背包. 第 ii 种物品最多有 sisi 件,每件体积是 vivi,价值是 wiwi. 求解将哪些物品装入背包,可使物品体积总和不超过背包 ...

  5. 51nod 多重背包问题(动态规划)

    多重背包问题 一个背包,承量有限为W,有n种物体,第i种物体,价值Vi,占用重量为 Wi,且有Ci件,选择物品若干放入背包,使得总重量不超过背包的承重.总价值最大? 输入 第1行,2个整数,N和W中间 ...

  6. C语言-多重背包问题

    多重背包问题 问题:有N种物品和一个容量为V的背包.第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大. 分 ...

  7. 多重背包问题II

    多重背包问题II 总体积是m,每个小物品的体积是A[i] ,每个小物品的数量是B[i],每个小物品的价值是C[i] 求能够放入背包内的最大物品能够获得的最大价值 和上一个很类似 上一题体积就是价值,这 ...

  8. 【动态规划/多重背包问题】POJ1014-Dividing

    多重背包问题的优化版来做,详见之前的动态规划读书笔记. dp[i][j]表示前i中数加得到j时第i种数最多剩余几个(不能加和得到i的情况下为-1)递推式为: dp[i][j]=mi(dp[i-1][j ...

  9. poj 1742 多重背包问题 dp算法

    题意:硬币分别有 A1.....An种,每种各有C1......Cn个,问组成小于m的有多少种 思路:多重背包问题 dp[i][j]表示用前i种硬币组成j最多剩下多少个  dp=-1的表示凑不齐 dp ...

随机推荐

  1. 解决Access连接 accdb 不可识别的数据库格式异常

    在Access07之前的数据库后缀名均为*.mdb 而连接字符串写成Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\myFolder\*.mdb ;Pe ...

  2. laravel5.2 学习之服务提供者

    契约接口:app\Contracts\LanguageContract.php <?php namespace App\Contracts; interface LanguageContract ...

  3. 负载均衡 IO etc.

    IO多路复用之epoll总结 ↑2013年8月21日11:49:44 EPOLL下的accept(不错的blog) 关于TCP封包.粘包.半包 linux内核TCP相关参数解释 ↑2013年8月14日 ...

  4. 開賣!下集 -- ASP.NET 4.5 專題實務(II)-範例應用與 4.5新功能【VB/C# 雙語法】

    開賣!下集 -- ASP.NET 4.5 專題實務(II)-範例應用與 4.5新功能[VB/C# 雙語法] 我.....作者都沒拿到書呢! 全台灣最專業的電腦書店 -- 天瓏書局 已經開賣了! 感謝天 ...

  5. 最大子列和CT 01-复杂度2 Maximum Subsequence Sum

    Given a sequence of K integers { N​1​​, N​2​​, ..., N​K​​ }. A continuous subsequence is defined to ...

  6. SRF之权限控制

    框架目前提供url访问.菜单和页面元素的权限控制和数据权限,权限基于角色来分配,1个用户可以属于多个角色,权限项分模块.页面.操作3级别,其中模块.页面用于url和菜单的控制,操作是对页面元素的控制. ...

  7. ListView与GridView异步加载图片

    原理很简单,主要是用到了回调方法,下面是异步加载图片的类 <span style="font-size:16px;">package com.xxx.xxx; impo ...

  8. linux安装ruby

    可以使用 sudo apt-get install ruby 的方式安装,但一般这种方式安装的版本比较旧.另外也可以用以下方式安装新的版本. 1. 首先更新软件源,使用国内的.参考:http://wi ...

  9. OpenStack的bridge_sto off的解释

    北京_张华(28620211) 2014/1/27 星期一 11:10:57传统的网络是通过STP协议来避免交换机在二层形成环路,但是对于虚拟交换机,因为有东西向的流量,故将bridge_stp设成o ...

  10. System.IO之内存映射文件共享内存

    内存映射文件是利用虚拟内存把文件映射到进程的地址空间中去,在此之后进程操作文件,就 像操作进程空间里的地址一样了,比如使用c语言的memcpy等内存操作的函数.这种方法能够很好的应用在需要频繁处理一个 ...