一大波模板正在靠近

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的更多相关文章

  1. 背包dp整理

    01背包 动态规划是一种高效的算法.在数学和计算机科学中,是一种将复杂问题的分成多个简单的小问题思想 ---- 分而治之.因此我们使用动态规划的时候,原问题必须是重叠的子问题.运用动态规划设计的算法比 ...

  2. hdu 5534 Partial Tree 背包DP

    Partial Tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid= ...

  3. 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 ...

  4. 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/ ...

  5. noj [1479] How many (01背包||DP||DFS)

    http://ac.nbutoj.com/Problem/view.xhtml?id=1479 [1479] How many 时间限制: 1000 ms 内存限制: 65535 K 问题描述 The ...

  6. HDU 1011 树形背包(DP) Starship Troopers

    题目链接:  HDU 1011 树形背包(DP) Starship Troopers 题意:  地图中有一些房间, 每个房间有一定的bugs和得到brains的可能性值, 一个人带领m支军队从入口(房 ...

  7. BZOJ 1004: [HNOI2008]Cards( 置换群 + burnside引理 + 背包dp + 乘法逆元 )

    题意保证了是一个置换群. 根据burnside引理, 答案为Σc(f) / (M+1). c(f)表示置换f的不动点数, 而题目限制了颜色的数量, 所以还得满足题目, 用背包dp来计算.dp(x,i, ...

  8. G - Surf Gym - 100819S -逆向背包DP

    G - Surf Gym - 100819S 思路 :有点类似 逆向背包DP , 因为这些事件发生后是对后面的时间有影响. 所以,我们 进行逆向DP,具体 见代码实现. #include<bit ...

  9. 树形DP和状压DP和背包DP

    树形DP和状压DP和背包DP 树形\(DP\)和状压\(DP\)虽然在\(NOIp\)中考的不多,但是仍然是一个比较常用的算法,因此学好这两个\(DP\)也是很重要的.而背包\(DP\)虽然以前考的次 ...

  10. 【BZOJ1004】【HNOI2008】Cards 群论 置换 burnside引理 背包DP

    题目描述 有\(n\)张卡牌,要求你给这些卡牌染上RGB三种颜色,\(r\)张红色,\(g\)张绿色,\(b\)张蓝色. 还有\(m\)种洗牌方法,每种洗牌方法是一种置换.保证任意多次洗牌都可用这\( ...

随机推荐

  1. centos或ubuntu下手动安装jdk8

    https://blog.csdn.net/pang_ping/article/details/80570011 https://blog.csdn.net/u012707739/article/de ...

  2. Could not find JSON in http://updates.jenkins-ci.org/update-center.json?id=default&version=2.7.4

    14-Sep-2016 21:43:58.241 INFO [Download metadata thread] hudson.model.AsyncPeriodicWork$1.run Finish ...

  3. zabbix使用mysql模板监控mysql

    出现监控项访问拒绝的信息 解决方法是: 在 mysql的 my.cnf 配置中增加 [mysql] user=zabbix password=zabbix [mysqladmin] user=zabb ...

  4. BZOJ 1724 [Usaco2006 Nov]Fence Repair 切割木板:贪心 优先队列【合并果子】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1724 题意: 你要将一块长木板切成n段,长度分别为a[i](长木板的长度 = ∑ a[i] ...

  5. ZOJ 3329 One Person Game:期望dp【关于一个点成环——分离系数】

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3329 题意: 给你面数分别为k1,k2,k3的三个骰子. 给定a ...

  6. linux应用之jdk环境的安装(centos)

    一.yum安装 1.执行:yum search jdk 已加载插件:fastestmirror, securityLoading mirror speeds from cached hostfile ...

  7. MD5算法的简单编写

    package com.t_09; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; ...

  8. 1131 Subway Map(30 分)

    In the big cities, the subway systems always look so complex to the visitors. To give you some sense ...

  9. ACM学习历程—Codeforces 446C DZY Loves Fibonacci Numbers(线段树 && 数论)

    Description In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence ...

  10. bzoj 3267: KC采花&&3272&&3638&&3502 线段树

    题目大意 给定一个长为n的序列,维护两种操作: 1.单点修改 2.在[l,r]这段区间中取k个互不相交的子段,使子段之和最大. \(n \leq 50000,k \leq 20\) 题解 四倍经验.( ...