01背包问题(每个物品最多选一次)

AcWing 2. 0/1背包问题

朴素の版本:

#include <bits/stdc++.h>
using namespace std;
const int N=1010;
int vi[N],wi[N],f[N][N];
int n,v;
int main(){
scanf("%d%d",&n,&v);
for(int i=1;i<=n;i++) scanf("%d%d",&vi[i],&wi[i]);
for(int i=1;i<=n;i++){
for(int j=0;j<=v;j++){
f[i][j]=f[i-1][j];
if(j>=v[i]) f[i][j]=max(f[i][j],f[i-1][j-vi[i]]+wi[i]);
}
}
printf("%d",f[n][v]);
return 0;
}

滚动数组优化の版本:

#include <bits/stdc++.h>
using namespace std;
const int N=1010;
int vi[N],wi[N],f[N][N];
int n,v;
int main(){
scanf("%d%d",&n,&v);
for(int i=1;i<=n;i++) scanf("%d%d",&vi[i],&wi[i]);
for(int i=1;i<=n;i++){
for(int j=0;j<=v;j++){
f[i&1][j]=f[(i-1)&1][j];
if(j>=v[i]) f[i&1][j]=max(f[i&1][j],f[(i-1)&1][j-vi[i]]+wi[i]);
}
}
printf("%d",f[n&1][v]);
return 0;
}

有不了解滚动数组的读者,可以参考以下大佬博客:

https://www.cnblogs.com/kimsimple/p/6883871.html

终极优化の版本:(二维变一维)

#include <bits/stdc++.h>
using namespace std;
const int N=1010;
int vi[N],wi[N],f[N];
int n,v;
int main(){
scanf("%d%d",&n,&v);
for(int i=1;i<=n;i++) scanf("%d%d",&vi[i],&wi[i]);
for(int i=1; i<=n; i++){
for(int j=v; j>=vi[i]; j--){
f[j]=max(f[j],f[j-vi[i]]+wi[i]);
}
}
printf("%d", f[v]);
return 0;
}

完全背包问题(每个物品可以选无限多次)

AcWing 3. 完全背包问题

朴素の版本:

#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int vi[N],wi[N],f[N][N];
int n,v;
int main(){
scanf("%d%d",&n,&v);
for(int i=1;i<=n;i++) scanf("%d%d",&vi[i],&wi[i]);
for(int i=1;i<=n;i++){
for(int j=0;j<=v;j++){
for(int k=0;k*vi[i]<=j;k++){
f[i][j]=max(f[i][j],f[i-1][j-k*vi[i]]+k*wi[i]);
}
}
}
printf("%d", f[n][v]);
return 0;
}

二维数组の版本:

二维数组优化の版本:

#include <bits/stdc++.h>
using namespace std;
const int N=1010;
int vi[N],wi[N],f[N][N];
int n,v;
int main(){
scanf("%d%d",&n,&v);
for(int i=1;i<=n;i++) scanf("%d%d",&vi[i],&wi[i]);
for(int i=1;i<=n;i++){
for(int j=0;j<=v;j++){
f[i][j]=f[i-1][j];
if(j>=vi[i]) f[i][j]=max(f[i][j],f[i][j-vi[i]]+wi[i]);
}
}
printf("%d",f[n][v]);
return 0;
}

终极优化の版本:

#include <bits/stdc++.h>
using namespace std;
const int N=1010;
int vi[N],wi[N],f[N];
int n,v;
int main(){
scanf("%d%d",&n,&v);
for(int i=1;i<=n;i++) scanf("%d%d",&vi[i],&wi[i]);
for(int i=1;i<=n;i++){
for(int j=vi[i];j<=v;j++){
f[j]=max(f[j],f[j-vi[i]]+wi[i]);
}
}
printf("%d",f[v]);
return 0;
}

多重背包问题(有限次地选每件物品)---二进制优化版本

多重背包问题

二进制拆分の版本:

#include <bits/stdc++.h>
using namespace std;
const int N=15000;
const int M=2010;
int n,m,cnt;
int f[M];
int v[N],w[N],s[N];
int main(){
int vi=0,wi=0,si=0;
scanf("%d%d", &n, &m);
//二进制拆分
for(int i=1;i<=n;i++){
scanf("%d%d%d",&vi,&wi,&si);
if(si>m/vi) si=m/vi;
for(int j=1;j<=si;j<<=1){
v[++cnt]=j*vi;
w[cnt]=j*wi;
si-=j;
}
if(si>0){
v[++cnt]= si*vi;
w[cnt]=si*wi;
}
}
//0/1背包
for(int i=1;i<=cnt;i++){
for(int j=m;j>=v[i];j--){
f[j] = max(f[j],f[j-v[i]]+w[i]);
}
}
printf("%d",f[m]);
return 0;
}

分组背包问题(n组,每组只能选一种并且最多选一次)

分组背包问题

朴素の版本:

#include <bits/stdc++.h>
using namespace std;
const int N=40;
const int M=210;
int n,m,t;
int v[N],c[N];
int g[15][N],f[15][M];
int main(){
int x=0;
scanf("%d%d%d",&m,&n,&t);
for(int i=1;i<=n;i++){
scanf("%d%d%d",&v[i],&c[i],&x);
g[x][++g[x][0]]=i;
} for(int i=1;i<=t;i++){
for(int j=0;j<=m;j++){
f[i][j]=f[i-1][j];
for(int k=1;k<=g[i][0];k++){
if(j>=v[g[i][k]]) {
x=g[i][k];
f[i][j]=max(f[i][j],f[i-1][j-v[x]]+c[x]);
}
}
}
}
printf("%d",f[t][m]);
return 0;
}

终极优化の版本:

#include <bits/stdc++.h>
using namespace std;
const int N=40;
const int M=210;
int n,m,t;
int v[N],c[N],g[15][N];
int f[M];
int main(){
int x=0;
scanf("%d%d%d",&m,&n,&t);
for(int i=1;i<=n;i++){
scanf("%d%d%d",&v[i],&c[i],&x);
g[x][++g[x][0]]=i;
} for(int i=1;i<=t;i++){
for(int j=m;j>=0;j--){
for(int k=1; k<=g[i][0]; k++){
if(j>=v[g[i][k]]) {
x=g[i][k];
f[j]=max(f[j],f[j-v[x]]+c[x]);
}
}
}
}
printf("%d",f[m]);
return 0;
}

以上就是背包dp中几个类型的问题了,如有错误欢迎大家在评论区指正小蒟蒻博主的错误~

本文图片来自https://blog.csdn.net/m0_73569492/article/details/129864277鸣谢大佬

#一名爱打篮球的oier#

动态规划(二)——背包dp的更多相关文章

  1. [luogu1156]垃圾陷阱_动态规划_背包dp

    垃圾陷阱 luogu-1156 题目大意:Holsteins在距离地面D英尺的地方,FJ间隔时间ti会往下扔第i个垃圾.Holsteins对待每一个垃圾都会选择吃掉或者垫高.Holsteins有10个 ...

  2. [bzoj1708][Usaco2007 Oct]Money奶牛的硬币_动态规划_背包dp

    Money奶牛的硬币 bzoj-1708 Usaco-2007 Oct 题目大意:在创立了她们自己的政权之后,奶牛们决定推广新的货币系统.在强烈的叛逆心理的驱使下,她们准备使用奇怪的面值.在传统的货币 ...

  3. 算法竞赛模板 动态规划之背包DP

    ① 01背包 有n件物品和一个容量为v的背包.第i件物品的价值是c[i],体积是w[i].求解将哪些物品装入背包可使价值总和最大. 这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放. ...

  4. [bzoj1606][Usaco2008 Dec]Hay For Sale 购买干草_动态规划_背包dp

    Hay For Sale 购买干草 bzoj-1606 Usaco-2008 Dec 题目大意:约翰遭受了重大的损失:蟑螂吃掉了他所有的干草,留下一群饥饿的牛.他乘着容量为C(1≤C≤50000)个单 ...

  5. [bzoj2748][HAOI2012]音量调节_动态规划_背包dp

    音量调节 bzoj-2748 HAOI-2012 题目大意:有一个初值,给你n个$\delta$值,求最后不超过给定的限制的情况下的改变的最大值.每个$\delta$值可以+也可以-. 注释:$1\l ...

  6. [USACO Section 5.3]量取牛奶 Milk Measuring (动态规划,背包$dp$)

    题目链接 Solution 完全背包 \(dp\) , 同时再加一个数组 \(v[i][j]\) 记录当总和为\(j\) 时第 \(i\) 种物品是否被选. 为保证从小到大和字典序,先将瓶子按大小排序 ...

  7. 背包dp整理

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

  8. 动态规划_线性dp

    https://www.cnblogs.com/31415926535x/p/10415694.html 线性dp是很基础的一种动态规划,,经典题和他的变种有很多,比如两个串的LCS,LIS,最大子序 ...

  9. 「kuangbin带你飞」专题十二 基础DP

    layout: post title: 「kuangbin带你飞」专题十二 基础DP author: "luowentaoaa" catalog: true tags: mathj ...

  10. Codeforces 2016 ACM Amman Collegiate Programming Contest A. Coins(动态规划/01背包变形)

    传送门 Description Hasan and Bahosain want to buy a new video game, they want to share the expenses. Ha ...

随机推荐

  1. Nebula Graph 在大规模数据量级下的实践和定制化开发

    本文作者系微信技术专家李本利 图数据在社交推荐.多跳实时计算.风控和安全等领域有可期待的前景.如何用图数据库高效存储和查询大规模异构图数据,是一个重大挑战.本文描述了开源分布式图数据库 Nebula ...

  2. 【专业技能】程序员的软件工程素养之画好 UML 时序图

    目录 前言 一.认识时序图 1.1时序图元素 1.2怎么使用 二.画好时序图 2.1一般步骤 2.2举个例子 2.3推荐工具 三.其它作用 四.文章小结 前言 笔者在本科的时候上过软件工程的专业课,也 ...

  3. Java 包装类的使用 + 小练习

    1 package com.bytezreo.ut; 2 3 import org.junit.Test; 4 5 /** 6 * 7 * @Description 包装类的使用 8 * @autho ...

  4. 微信小程序直播,腾讯云直播+微信小程序实现实时直播

    一:小程序代码端 小程序直播使用小程序组件 live-pusher 组件和live-player组件 首先开通直播权限 小程序开发工具内进行推流拉流都不会成功,所以需要使用两个手机进行推拉流测试: 1 ...

  5. ECharts 中国地图 vue

    <template> <div> <div id="china_map_box"> <div id="china_map&quo ...

  6. ble无线智能工牌解决方案技术解析

    场景需求  在无线智能工牌领域,团队做了几个实际场景的解决方案之后,积累了一些行业需求经验和技术经验.这里做一个总结,算是一种沉淀吧.场景一:居家养老,医护和护工人员定期上门服务,根据工作时长来发工资 ...

  7. python中往json中添加文件的方法

    一 前言: python中常用的一种方式,这里给大家列出来一下. 二 实例 比如,最简单的一个json文件 test_json = { "a": 1, "b": ...

  8. RTP网络包提取码流方法

    1.工具wireshark,官网最新的版本没有保存按键,建议使用3.4 链接:https://pan.baidu.com/s/1VHSGgojZPNtzyzV6RMVjkw 提取码:q51a 2.wi ...

  9. 【AtCoder Beginner Contest 330)】[E - Mex and Update ] 线段树+二分

    本题可以用线段树+二分的方式实现.代码如下: import java.io.IOException; import java.io.InputStreamReader; import java.io. ...

  10. 短小精悍的npm入门级保姆教程,一篇包会

    npm是什么? npm是一个强大的包管理工具,它使开发人员能够轻松地安装.更新和管理项目依赖的包.通过初始化一个package.json 文件,我们可以描述你的项目并记录其依赖关系.使用npm ins ...