背包dp
一大波模板正在靠近
1.01背包
问题:有n件物品和一个容量为v的背包,第i件物品的费用(即体积)是w[i],价值是v[i],求解将哪些物品装入背包可使这些物品的费用和不超过背包容量,且价值总和最大。
动态转移方程为f[j]=max(f[j],f[j-w[i]]+v[i]),注意关于背包容量要倒着循环,来保证每个物品只选一次
//二维
for(int i=;i<=n;i++)
for(int j=m;j>=;j--)
f[i][j]=max(f[i-][j],f[i-][j-w[i]]+v[i]);
cout<<f[n][m];
//一维
for(int i=;i<=n;i++)
for(int j=m;j>=;j--)
f[j]=max(f[j],f[j-w[i]]);
cout<<f[m];
2.完全背包
问题:有n种物品和一个容量为v的背包,每种物品都有无限件可用,第i种物品的费用是w[i],价值是v[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
动态转移方程为f[j]=max(f[j],f[j-w[i]]+v[i]),完全背包问题与01背包问题只有背包容量的循环次序不同
/*完全背包(无限件可用)*/
for(int i=;i<=n;i++)
for(int j=w[i];j<=m;j++)
f[j]=max(f[j],f[j-w[i]]+v[i]);
3.多重背包
问题:有n种物品和一个容量为v的背包,第i种物品最多有s[i]件可用,每件的费用是w[i],价值是v[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
//朴素算法
for(int i=;i<=n;i++)
for(int j=m;j>=;j--)
for(int k=;k<=s[i];k++)
{
if(j-w[i]*k<)break;
f[j]=max(f[j],f[j-w[i]*k]+v[i]*k);
}
cout<<f[m];
//二进制优化,转换为01背包
int n1=;
for(int i=;i<=n;i++)
{
cin>>vv>>ww>>s;
int t=;
while(s>=t)
{
w[++n1]=ww*t;
v[n1]=vv*t;
s-=t;
t*=;
}
w[++n1]=ww*s;
v[n1]=vv*s;
}
for(int i=;i<=n1;i++)
for(int j=m;j>=w[i];j--)
f[j]=max(f[j],f[j-w[i]]+v[i]);
cout<<f[m];
4.混合三种背包问题
问题:有的物品只可以取一次(01背包),有的物品可以取无限次(完全背包),有的物品可以取的次数有一个上限(多重背包),该怎么求解呢?
//朴素
for(int i=;i<=n;i++)
{
if(s[i]==-)//完全背包
{
for(int j=w[i];j<=m;j++)
f[j]=max(f[j],f[j-w[i]]+v[i]);
}
else
{
for(int k=;k<=s[i];k++)//循环件数
for(int j=m;j>=w[i];j--)
f[j]=max(f[j],f[k-w[i]]+v[i]);
}
}
cout<<f[m];
//二进制优化
for(int i=;i<=n;i++)
{
int ww,vv,ss;
int t=;
cin>>ww>>vv>>ss;
if(ss==-)
{w[++n1]=ww;v[n1]=vv;s[n1]=-;continue;}
if(ss==)
{w[++n1]=ww;v[n1]=vv;s[n1]=;continue;}
if(ss>)//多重背包
{
int t=;
while(ss>=t)
{
w[++n1]=ww*t;
v[n1]=vv*t;
s[n1]=;
ss-=t;
t*=;
}
if(ss>){
w[++n1]=ww*ss;
v[n1]=vv*ss;
s[n1]=;
}
continue;
}
}
for(int i=;i<=n1;i++)
{
if(s[i]==-)//完全背包
{
for(int j=w[i];j<=m;j++)
f[j]=max(f[j],f[j-w[i]]+v[i]);
}
else
{
for(int j=m;j>=w[i];j--)
f[j]=max(f[j],f[j-w[i]]+v[i]);
}
}
cout<<f[m];
5.二维费用背包
问题:二维费用的背包问题是指对于每件物品,具有两种不同的费用,选择这件物品必须同时付出这两种代价,对于每种代价都有一个可付出的最大值(背包容量),求选择物品可以得到最大的价值。设第i件物品所需的两种代价分别为w1[i]和w2[i],两种代价可付出的最大值(两种背包容量)分别为V和U,物品的价值为v[i]。
状态转移方程为:
f[i][j][k]=max(f[i-1][j][k],f[i-1][j-w1[i]][k-w2[i]]+v[i]);
/*二维费用的背包问题(与01背包相似)*/
for(int i=;i<=n;i++)
for(int j=m1;j>=w1[i];j--)
for(int k=m2;k>=w2[i];k--)
f[j][k]=max(f[j-w1[i]][k-w2[i]],f[i][j]);
cout<<f[m1][m2];
6.分组背包
问题:有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。这些物品被划分为若干组,每组中的物品互相冲突,最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
算法:
这个问题变成了每组物品有若干种策略:是选择本组的某一件,还是一件都不选。也就是说设f[k][v]表示前k组物品花费费用v能取得的最大权值,则有:
f[k][v]=max{f[k-1][v],f[k-1][v-c[i]]+w[i]|物品i属于组k}
使用一维数组的伪代码如下:
for 所有的组k//循环分组
for v=V..0//容量限制
for 所有的i属于组k//组内物品
f[v]=max{f[v],f[v-c[i]]+w[i]}
/*分组的背包问题*/
for(int i=;i<=n;i++)
{
int p;
cin>>w[i]>>v[i]>>p;
a[p][++a[p][]]=i;
}
for(int k=;k<=t;k++)
for(int j=m;j>=;j--)
for(int i=;i<=a[k][];i++)
{
int tmp=a[k][i];//tmp代表k组中的第i个物品在所有物品中的序号
f[j]=max(f[j],f[j-w[tmp]]+v[tmp]);
}
cout<<f[m];
7.背包问题的方案总数
对于一个给定了背包容量、物品费用的背包问题,除了再给定每个物品的价值后求可得到的最大价值外,还可以得到装满背包或将背包装至某一指定容量的方案总数。对于这类改变问法的问题,一般只需将状态转移方程中的max改成sum即可。例如若每件物品均是0-1背包中的物品,转移方程即为f[j]=sum{f[j],f[j-w[i]]+v[i]},即f[j]+=f[j-w[i]],初始条件f[0]=1。
事实上,这样做可行的原因在于状态转移方程已经考察了所有可能的背包组成方案.
/*背包问题的方案总数*/
//01背包求方案总数
for(int i=;i<=n;i++)
for(int j=m;j>=w[i];j++)
f[j]+=f[j-w[i]];
cout<<f[m];
背包dp的更多相关文章
- 背包dp整理
01背包 动态规划是一种高效的算法.在数学和计算机科学中,是一种将复杂问题的分成多个简单的小问题思想 ---- 分而治之.因此我们使用动态规划的时候,原问题必须是重叠的子问题.运用动态规划设计的算法比 ...
- hdu 5534 Partial Tree 背包DP
Partial Tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid= ...
- HDU 5501 The Highest Mark 背包dp
The Highest Mark Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?p ...
- Codeforces Codeforces Round #319 (Div. 2) B. Modulo Sum 背包dp
B. Modulo Sum Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/577/problem/ ...
- noj [1479] How many (01背包||DP||DFS)
http://ac.nbutoj.com/Problem/view.xhtml?id=1479 [1479] How many 时间限制: 1000 ms 内存限制: 65535 K 问题描述 The ...
- HDU 1011 树形背包(DP) Starship Troopers
题目链接: HDU 1011 树形背包(DP) Starship Troopers 题意: 地图中有一些房间, 每个房间有一定的bugs和得到brains的可能性值, 一个人带领m支军队从入口(房 ...
- BZOJ 1004: [HNOI2008]Cards( 置换群 + burnside引理 + 背包dp + 乘法逆元 )
题意保证了是一个置换群. 根据burnside引理, 答案为Σc(f) / (M+1). c(f)表示置换f的不动点数, 而题目限制了颜色的数量, 所以还得满足题目, 用背包dp来计算.dp(x,i, ...
- G - Surf Gym - 100819S -逆向背包DP
G - Surf Gym - 100819S 思路 :有点类似 逆向背包DP , 因为这些事件发生后是对后面的时间有影响. 所以,我们 进行逆向DP,具体 见代码实现. #include<bit ...
- 树形DP和状压DP和背包DP
树形DP和状压DP和背包DP 树形\(DP\)和状压\(DP\)虽然在\(NOIp\)中考的不多,但是仍然是一个比较常用的算法,因此学好这两个\(DP\)也是很重要的.而背包\(DP\)虽然以前考的次 ...
- 【BZOJ1004】【HNOI2008】Cards 群论 置换 burnside引理 背包DP
题目描述 有\(n\)张卡牌,要求你给这些卡牌染上RGB三种颜色,\(r\)张红色,\(g\)张绿色,\(b\)张蓝色. 还有\(m\)种洗牌方法,每种洗牌方法是一种置换.保证任意多次洗牌都可用这\( ...
随机推荐
- IO多路复用之Reactor模式
首先,我们来看看同步和异步. 在处理 IO 的时候,阻塞和非阻塞都是同步 IO.只有使用了特殊的 API 才是异步 IO. 接下来,我们来看看Linux下的三大同步IO多路复用函数 fcntl(fd, ...
- oracle-数据库的各种-锁-详解
数据库是一个多用户使用的共享资源.当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况.若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性. 如果是单用户的 ...
- Spring Boot2.0之多环境配置
本地开发环境 测试环境 实际项目中 区分不同的环境配置文件信息 首先创建三种不同场景下的配置文件: 内容分别是: ###dev http_url="dev" ###prdhttp_ ...
- javascript正则(带g符号) 多次调用test 结果交替出现
链接:https://segmentfault.com/q/1010000000582051 http://stackoverflow.com/questions/2851308/why-does-m ...
- Android SDK Manager更新问题
1.如果是windows7,那么"开始-->所有程序-->Android SDK Tools-->右键SDK Manager-->以管理员身份运行(A)"2 ...
- redis持久化【转】
Redis是一种高级key-value数据库.它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富.有字符串,链表,集 合和有序集合.支持在服务器端计算集合的并,交和补集(diff ...
- html5--1.11列表
html5--1.11列表 学习要点: 无序列表 有序列表 列表的属性 自定义列表 1.无序列表的基本格式 ul(unorder line)标签里面放li标签就好了,每一项就是一个li(LineIte ...
- swoole_table
Memory Swoole提供了7个内存操作的模块,在多进程编程中可以帮助开发者实现一些特殊的需求. swoole_table 是基于共享内存和锁实现的超高性能,并发数据结构
- [acm]HDOJ 2059 龟兔赛跑
题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=2059 起点和终点,共n+2个点,n+2个状态,简单DP即可. //11512698 2014-08- ...
- k8s-应用快速入门(ma)
[root@k8s-master ~]# kubectl run nginx-deploy --image=nginx:1.14-alpine --port=80 --replicas=1 deplo ...