DP大作战——多重背包
题目描述
在之前的上机中,零崎已经出过了01背包和完全背包,也介绍了使用-1初始化容量限定背包必须装满这种小技巧,接下来的背包问题相对有些难度,可以说是01背包和完全背包的进阶问题。
多重背包:物品可以有0-n件。
对于第i种物品,我们有取0件,1件…n [ i ] 件共n [ i ] +1种策略,状态转移方程为f [ i ] [ v ] = max { f [ i - 1 ] [ v - k × c [ i ] ] + k × w [ i ] | 0 <=k<= n [ i ] }。在这里,很自然的有一种策略可以将其转化为01背包,即将物品换为n[i]件01背包中的物品,但是复杂度为O(VΣni),时间复杂度没有降低。实际上,对于所有类似情况,我们都可以利用二进制求和来降低时间复杂度。即将物品替换为价值和费用 * 系数=1,2,2^2,…,2^k,n[i]-2^k+1的物品。系数之和为n [ i ],表明不能取到多于n [ i ]件物品,但可以取到0…n[ i ]中任意一个整数件。利用这一优化,算法事件复杂度可以降到O(VΣlogni)。
实际上F [ i ] [ j ] 只依赖于 F [ i-1 ] [ j - k * w [ i ] ],这里依赖项之间构成了一个 { j mod w [ i ] }剩余类,不同剩余类之间无关,注意到这点利用单调队列,每个状态均摊O(1)的时间,可以进一步将算法时间复杂度优化至O(VN)级别的,不过在此不再详细阐述。(其实也就是NOIP程度,放在大学应该可以接受,但是这个优化个人感觉已经脱离dp)
DD大牛给出的伪代码。
def MultiplePack(F,C,W,M)
if C * M >= V
CompletePack(F,C,W)
return //考虑这里为什么可以直接用完全背包
k := 1
while k < M
ZeroOnePack(kC,kW)
M := M - k
k := 2k
ZeroOnePack(C M,W M)
输入
第一个数为数据组数n 1<=n<=10
接下来n组测试数据,每组测试数据由2部分组成。
第一行为背包容量V,物品种类数N。1<=V<=30000,1<=N<=200
接下来N行每行三个数为物品价值v,物品重量w,物品件数M。
1<=v,w<=200, 1<=M<=25
输出
对于每组数据,输出一行,背包能容纳的最大物品价值
输入样例
1
10 2
1 2 3
2 3 2
输出样例
6 题目来源:http://biancheng.love/contest/10/problem/E/index
解题思路:
问题属于背包问题,同时包括了0-1和完全背包,因此为多重背包问题。
按照之前的想法,只要判断每件物品的件数,可以确定对于该物品是使用0-1背包还是完全背包。
0-1背包的代码:
void Zeronepack(int w,int v)
{
for(int i=V; i>=w; i--)
if(dp[i]<dp[i-w]+v)
dp[i]=dp[i-w]+v;
}
完全背包的代码:
void Compack(int w,int v)
{
for(int i=w; i<=V; i++)
if(dp[i]<dp[i-w]+v)
dp[i]=dp[i-w]+v;
}
本题需要利用0-1背包以及完全背包来解决多重背包问题
代码:
#include <bits/stdc++.h>
#include<stdio.h>
#include<string.h>
int dp[];
int V,N;
void Compack(int w,int v)
{
for(int i=w; i<=V; i++)
if(dp[i]<dp[i-w]+v)
dp[i]=dp[i-w]+v;
} void Zeronepack(int w,int v)
{
for(int i=V; i>=w; i--)
if(dp[i]<dp[i-w]+v)
dp[i]=dp[i-w]+v;
} int main()
{
int kase,v,w,m;
scanf("%d",&kase);
while(kase--)
{
memset(dp,,sizeof(dp));
scanf("%d%d",&V,&N);
for(int i=; i<=N; i++)
{
scanf("%d%d%d",&v,&w,&m);
if(w*m>=V)
Compack(w,v);
else
{
for(int j=; j<m; j<<)
{
Zeronepack(j*w,j*v);
m-=j;
}
Zeronepack(m*w,m*v);
}
}
printf("%d\n",dp[V]);
}
return ;
}
DP大作战——多重背包的更多相关文章
- DP大作战—组合背包
题目描述 组合背包:有的物品只可以取一次(01背包),有的物品可以取无限次(完全背包),有的物品可以取的次数有一个上限(多重背包). DD大牛的伪代码 for i = 1 to N if 第i件物品属 ...
- AlvinZH掉坑系列讲解(背包DP大作战H~M)
本文由AlvinZH所写,欢迎学习引用,如有错误或更优化方法,欢迎讨论,联系方式QQ:1329284394. 前言 动态规划(Dynamic Programming),是一个神奇的东西.DP只能意会, ...
- 963 AlvinZH打怪刷经验(背包DP大作战R)
963 AlvinZH打怪刷经验 思路 这不是一道普通的01背包题.大家仔细观察数据的范围,可以发现如果按常理来的话,背包容量特别大,你也会TLE. 方法一:考虑01背包的一个常数优化----作用甚微 ...
- 976 AlvinZH想回家(背包DP大作战T)
976 AlvinZH想回家 思路 如果在第i小时有一些飞机延误,那么一架飞机的c值越大,这一小时产生的损失也越大.而使这一小时产生的损失尽可能的小并不会导致接下来时间产生的损失增大.因此应当每一小时 ...
- 977 AlvinZH过生日(背包DP大作战S)
977 AlvinZH过生日 思路 难题.逆推DP. 要明确dp的状态只与是否有选择权有关,而与选择权在谁手里无关.因为不论选择权在谁手里,那个人都会尽可能的获得最大的蛋糕重量. dp[i]表示分配到 ...
- 991 AlvinZH的奇幻猜想----整数乘积plus(背包DP大作战P)
914 AlvinZH的奇幻猜想----整数乘积puls 思路 难题.动态规划. 将数字串按字符串输入,处理起来更方便些. dp[i][j]:表示str[0~i]中插入j个乘号时的乘积最大值.状态转移 ...
- 906 AlvinZH的奇幻猜想----整数乘积(背包DP大作战O)
906 AlvinZH的奇幻猜想----整数乘积 思路 难题.动态规划. 将数字串按字符串输入,处理起来更方便些. dp[i][j]:表示str[0~i]中插入j个乘号时的乘积最大值.状态转移方程为: ...
- 851 AlvinZH的鬼畜密码(背包DP大作战N)
851 AlvinZH的鬼畜密码 思路 难题.动态规划. 先判断字符串是否合理(可翻译),然后分段处理,每一小段用动态规划求出解法数. dp[i]:字符串str[0~i]的解法数.通过判断str[i] ...
- DP大作战—状态压缩dp
题目描述 阿姆斯特朗回旋加速式阿姆斯特朗炮是一种非常厉害的武器,这种武器可以毁灭自身同行同列两个单位范围内的所有其他单位(其实就是十字型),听起来比红警里面的法国巨炮可是厉害多了.现在,零崎要在地图上 ...
随机推荐
- 斜堆(一)之 C语言的实现
概要 本章介绍斜堆.和以往一样,本文会先对斜堆的理论知识进行简单介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现:实现的语言虽不同,但是原理如出一辙,选择其中之一进行了解即可.若文 ...
- django 快速实现登录
前言 对于web开来说,用户登陆.注册.文件上传等是最基础的功能,针对不同的web框架,相关的文章非常多,但搜索之后发现大多都不具有完整性,对于想学习web开发的新手来说不具有很强的操作性:对于web ...
- Xcode-显示代码行数
在Xcode菜单中选择Preferences命令,单击Text Editing选项图标,选中Linenumbers复选框.(快捷键苹果键+逗号打开preferences --> Text Edi ...
- 利用栈实现算术表达式求值(Java语言描述)
利用栈实现算术表达式求值(Java语言描述) 算术表达式求值是栈的典型应用,自己写栈,实现Java栈算术表达式求值,涉及栈,编译原理方面的知识.声明:部分代码参考自茫茫大海的专栏. 链栈的实现: pa ...
- ASP.NET HTTP模拟提交通用类 GET POST
用法: WebRequestSugar ws = new WebRequestSugar(); //可选参数 //ws.SetAccept //ws.SetContentType //ws.SetC ...
- 利用百度词典API和Volley网络库开发的android词典应用
关于百度词典API的说明,地址在这里:百度词典API介绍 关于android网络库Volley的介绍说明,地址在这里:Android网络通信库Volley 首先我们看下大体的界面布局!
- MVC知识点01
1:母版页都 放在View/Shared里面,而且全部的视图页面都可以去用母板页. **母板的应用要用到嵌套,@RenderBody();将别的网页的内容全部显示在此处,它就相当于一个占位符. 2:架 ...
- P6 EPPM 16 R1 文档和帮助系统
P6 EPPM 16 R1 文档和帮助系统 https://docs.oracle.com/cd/E74894_01/ http://docs.oracle.com/cd/E68202_01/clie ...
- SQL Server case when 日期字符串转换 多表查询 嵌套子查询
select distinct stu.*, dbo.GetClassNameByStudentCode(stu.Code) as ClassName, dbo.GetCourseNameByStud ...
- 关于foreach中对集合执行Add或者Remove操作引发枚举值被修改异常
方法传入集合List<string> ids; 执行操作后再次循环引发异常 foreach (string id in ids) { ids.Add("a"); } 更 ...