背包九讲(例题+代码)

article/2025/9/14 21:08:06

背包九讲

文章目录

  • 背包九讲
    • 01背包问题
    • 完全背包问题
    • 多重背包问题
      • 多重背包问题 I(二进制优化)
      • 多重背包问题 II(单调队列优化)
    • 混合背包问题
    • 二维费用的背包问题
    • 分组背包问题
    • 有依赖的背包问题
    • 背包问题求方案数
    • 背包问题求具体方案

脉络图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pEGLzdJj-1642346398405)(H:\codes\算法\背包九讲.assets\背包-16420904352541.png)]

01背包问题

题目:

N件物品、容量背包是 V。第 i 件物品的体积是 vi,价值是 wi每件物品只能使用一次

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。

输出最大价值

输入格式

第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。

接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。

输出格式

输出一个整数,表示最大价值。

数据范围

0<N,V≤1000
0<vi,wi≤1000

代码:

#include <bits/stdc++.h>using namespace std;const int N=1010;
int n,m;
int f[N];
int v[N],w[N];int main(){cin>>n>>m;for(int i=1;i<=n;++i) cin>>v[i]>>w[i];for(int i=1;i<=n;++i)for(int j=m;j>=v[i];--j)f[j]=max(f[j],f[j-v[i]]+w[i]);cout<<f[m]<<endl;return 0;        
}

完全背包问题

题目:

N件物品、容量背包是 V。第 i 件物品的体积是 vi,价值是 wi每件物品可以使用多次

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。

输出最大价值

输入格式

第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。

接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。

输出格式

输出一个整数,表示最大价值。

数据范围

0<N,V≤1000
0<vi,wi≤1000

代码:

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

多重背包问题

题目:

N件物品、容量背包是 V。第 i 件物品有si个,体积是 vi,价值是 wi每件物品使用次数不超过si

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。

输出最大价值

输入格式

第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。

接下来有 N 行,每行两个整数 vi,wi,si,用空格隔开,分别表示第 i 件物品的体积、价值和数量。

输出格式

输出一个整数,表示最大价值。

数据范围

0<N,V≤100
0<vi,wi,si≤100

代码:

#include <bits/stdc++.h>using namespace std;const int N=110;
int n,m;
int v[N],w[N],s[N];
int f[N][N];int main(){cin>>n>>m;for(int i=1;i<=n;++i) cin>>v[i]>>w[i]>>s[i];for(int i=1;i<=n;++i)for(int j=0;j<=m;++j)for(int k=0;k<=s[i]&&k*v[i]<=j;++k)f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+w[i]*k);cout<<f[n][m]<<endl;return 0;
}

多重背包问题 I(二进制优化)

题目:

N件物品、容量背包是 V。第 i 件物品有si个,体积是 vi,价值是 wi每件物品使用次数不超过si

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。

输出最大价值

输入格式

第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。

接下来有 N 行,每行两个整数 vi,wi,si,用空格隔开,分别表示第 i 件物品的体积、价值和数量。

输出格式

输出一个整数,表示最大价值。

数据范围

0<N≤1000
0<V≤2000
0<vi,wi,si≤2000

代码:

#include <bits/stdc++.h>using namespace std;const int N=12010,M=2010;
int n,m;
int v[N],w[N];
int f[N];int main(){cin>>n>>m;int cnt=0;for(int i=1;i<=n;++i){int a,b,s;cin>>a>>b>>s;int k=1;while(s>=k){cnt++;v[cnt]=a*k;w[cnt]=b*k;s-=k;k*=2;}if(s>0){cnt++;v[cnt]=a*s;w[cnt]=b*s;}}n=cnt;for(int i=1;i<=n;++i)for(int j=m;j>=v[i];--j)f[j]=max(f[j],f[j-v[i]]+w[i]);cout<<f[m]<<endl;return 0;
}

多重背包问题 II(单调队列优化)

题目:

N件物品、容量背包是 V。第 i 件物品有si个,体积是 vi,价值是 wi每件物品使用次数不超过si

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。

输入格式

第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。

接下来有 N 行,每行两个整数 vi,wi,si,用空格隔开,分别表示第 i 件物品的体积、价值和数量。

输出格式

输出一个整数,表示最大价值。

数据范围

0<N≤1000
0<V≤20000
0<vi,wi,si≤20000

代码:

#include <bits/stdc++.h>using namespace std;const int N=20010;
int n,m;
int f[N],g[N],q[N];int main(){cin>>n>>m;for(int i=0;i<n;++i){int v,w,s;cin>>v>>w>>s;memcpy(g,f,sizeof f);for(int j=0;j<v;++j){int hh=0,tt=-1;for(int k=j;k<=m;k+=v){if(hh<=tt&&q[hh]<k-s*v)hh++;while(hh<=tt&&g[q[tt]]-(q[tt]-j)/v*w<=g[k]-(k-j)/v*w)tt--;q[++tt]=k;f[k]=g[q[hh]]+(k-q[hh])/v*w;}}}cout<<f[m]<<endl;return 0;
}

混合背包问题

N件物品、容量背包是 V。

物品一共有三类:

  • 第一类物品只能用1次(01背包);
  • 第二类物品可以用无限次(完全背包);
  • 第三类物品最多只能用 si次(多重背包);

每种体积是 vi,价值是 wi

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。

输入格式

第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。

接下来有 N 行,每行三个整数 vi,wi,si,用空格隔开,分别表示第 i 种物品的体积、价值和数量。

  • si=−1 表示第 i 种物品只能用1次;
  • si=0 表示第 i 种物品可以用无限次;
  • si>0 表示第 i 种物品可以使用 si 次;

输出格式

输出一个整数,表示最大价值。

数据范围

0<N,V≤1000
0<vi,wi≤1000
−1≤si≤1000

代码:

#include <bits/stdc++.h>using namespace std;const int N=1010;
int n,m;
int f[N];int main(){cin>>n>>m;for(int i=0;i<n;++i){int v,w,s;cin>>v>>w>>s;if(!s){for(int j=v;j<=m;++j)f[j]=max(f[j],f[j-v]+w);}else {if(s==-1) s=1;for(int k=1;k<=s;k*=2){for(int j=m;j>=k*v;--j){f[j]=max(f[j],f[j-k*v]+w*k);}s-=k;}if(s){for(int j=m;j>=s*v;--j){f[j]=max(f[j],f[j-s*v]+s*w);}}}}cout<<f[m]<<endl;return 0;
}

二维费用的背包问题

题目:

N件物品、容量背包是 V、背包能承受的最大重量是 M。第 i 件物品的体积是 vi,价值是 wi,重量是 mi每件物品只能使用一次

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,总重量不超过背包可承受的最大重量,且总价值最大。

输入格式

第一行三个整数,N,V,M,用空格隔开,分别表示物品件数、背包容积和背包可承受的最大重量。

接下来有 NN 行,每行三个整数 vi,mi,wi,用空格隔开,分别表示第 i 件物品的体积、重量和价值。

输出格式

输出一个整数,表示最大价值。

数据范围

0<N≤1000
0<V,M≤100
0<vi,mi≤100
0<wi≤1000

代码:

#include <bits/stdc++.h>using namespace std;const int N=110;
int n,V,M;
int f[N][N];int main(){cin>>n>>V>>M;for(int i=0;i<n;++i){int v,m,w;cin>>v>>m>>w;for(int j=V;j>=v;--j)for(int k=M;k>=m;--k)f[j][k]=max(f[j][k],f[j-v][k-m]+w);}cout<<f[V][M]<<endl;return 0;
}

分组背包问题

题目:

N件物品、容量背包是 V。每组物品有若干个,同一组内的物品最多只能选一个。每件物品的体积是 vij,价值是 wij,其中 i 是组号,j 是组内编号。

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大

输入格式

第一行有两个整数 N,V 用空格隔开,分别表示物品组数和背包容量。

接下来有 N 组数据:

  • 每组数据第一行有一个整数 Si,表示第 i 个物品组的物品数量;
  • 每组数据接下来有 Si 行,每行有两个整数 vij,wij,用空格隔开,分别表示第 i 个物品组的第 j 个物品的体积和价值;

输出格式

输出一个整数,表示最大价值。

数据范围

0<N,V≤100
0<Si≤100
0<vij,wij≤100

代码:

#include <bits/stdc++.h>using namespace std;const int N=110;
int n,m;
int v[N][N],w[N][N],s[N];
int f[N];int main(){cin>>n>>m;for(int i=1;i<=n;++i){cin>>s[i];for(int j=0;j<s[i];++j)cin>>v[i][j]>>w[i][j];}for(int i=1;i<=n;++i)for(int j=m;j>=0;--j)for(int k=0;k<s[i];++k)if(v[i][k]<=j)f[j]=max(f[j],f[j-v[i][k]]+w[i][k]);cout<<f[m]<<endl;return 0;
}

有依赖的背包问题

有 N 个物品和一个容量是 V 的背包。

物品之间具有依赖关系,且依赖关系组成一棵树的形状。如果选择一个物品,则必须选择它的父节点。

如下图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HDifyHiQ-1642346398407)(H:\codes\算法\背包九讲.assets\1_bb51ecbcd2-QQ图片20181018170337.png)]
如果选择物品5,则必须选择物品1和2。这是因为2是5的父节点,1是2的父节点。

每件物品的编号是 i,体积是 vi,价值是 wi,依赖的父节点编号是 pi。物品的下标范围是 1…N。

求解将哪些物品装入背包,可使物品总体积不超过背包容量,且总价值最大。

输出最大价值。

输入格式

第一行有两个整数 N,V,用空格隔开,分别表示物品个数和背包容量。

接下来有 N 行数据,每行数据表示一个物品。
第 ii 行有三个整数 vi,wi,pi,用空格隔开,分别表示物品的体积、价值和依赖的物品编号。
如果 pi=−1,表示根节点。 数据保证所有物品构成一棵树。

输出格式

输出一个整数,表示最大价值。

数据范围

1≤N,V≤100
1≤vi,wi≤100

父节点编号范围:

  • 内部结点:1≤pi≤N;
  • 根节点 pi=−1;

代码:

#include <bits/stdc++.h>using namespace std;const int N=110;
int n,m;
int v[N],w[N];
int h[N],e[N],ne[N],idx;
int f[N][N];void add(int a,int b){e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}void dfs(int u){for(int i=h[u];i!=-1;i=ne[i]){int son=e[i];dfs(e[i]);for(int j=m-v[u];j>=0;--j){for(int k=0;k<=j;++k){f[u][j]=max(f[u][j],f[u][j-k]+f[son][k]);}}}for(int i=m;i>=v[u];--i)f[u][i]=f[u][i-v[u]]+w[u];for(int i=0;i<v[u];++i)f[u][i]=0;
}int main(){cin>>n>>m;memset(h,-1,sizeof h);int root;for(int i=1;i<=n;++i){int p;cin>>v[i]>>w[i]>>p;if(p==-1) root=i;else add(p,i);}dfs(root);cout<<f[root][m]<<endl;return 0;
}

背包问题求方案数

N件物品、容量背包是 V。第 i 件物品的体积是 vi,价值是 wi每件物品只能使用一次

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。

输出最优选法的方案数。注意答案可能很大,请输出答案模 109+7 的结果。

输入格式

第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。

接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。

输出格式

输出一个整数,表示方案数模 109+7 的结果。

数据范围

0<N,V≤1000
0<vi,wi≤1000

代码:

#include <bits/stdc++.h>using namespace std;const int N=1010,mod=1e9+7;
int n,m;
int f[N],g[N];int main(){cin>>n>>m;memset(f,-0x3f,sizeof f);f[0]=0;g[0]=1;for(int i=0;i<n;++i){int v,w;cin>>v>>w;for(int j=m;j>=v;--j){int maxv=max(f[j],f[j-v]+w);int cnt=0;if(maxv==f[j]) cnt+=g[j];if(maxv==f[j-v]+w) cnt+=g[j-v];g[j]=cnt%mod;f[j]=maxv;}}int res=0;for(int i=0;i<=m;++i) res=max(res,f[i]);int cnt=0;for(int i=0;i<=m;++i)if(res==f[i])cnt=(cnt+g[i])%mod;cout<<cnt<<endl;return 0;
}

背包问题求具体方案

N件物品、容量背包是 V。第 i 件物品的体积是 vi,价值是 wi每件物品只能使用一次

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。

输出字典序最小的方案

输入格式

第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。

接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。

输出格式

输出一行,包含若干个用空格隔开的整数,表示最优解中所选物品的编号序列,且该编号序列的字典序最小。

物品编号范围是 1…N。

数据范围

0<N,V≤1000
0<vi,wi≤1000

代码:

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

题目来源


http://chatgpt.dhexx.cn/article/aDXhyT7W.shtml

相关文章

背包九讲.

背包九讲 背包问题完全背包问题多重背包问题 I多重背包问题 II多重背包问题 III混合背包问题二维费用的背包问题分组背包问题有依赖的背包问题背包问题求方案数背包问题求具体方案 背包问题 有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。 第 i 件物品的体积是 v…

背包九讲——全篇详细理解与代码实现

DD_engi 背包九讲的个人整理 写在前面 Last Modified:2021/9 博主重新审读了一下整篇文章&#xff0c;以我现在更进一步的理解更新了文章中的部分内容&#xff0c;有问题及疑惑可随时评论或私信&#xff0c;会及时回复&#xff01;&#xff01;! 更新进度&#xff1a;9/9:⑦有…

22 springboot依赖注入三种方式

1 基于构造函数的依赖注入 Spring 基于构造函数的依赖注入_w3cschoolJ虽然当前有关Spring Framework&#xff08;5.0.3&#xff09;的文档仅定义了两种主要的注入类型&#xff0c;但实际上有三种 public class UserServiceImpl implents UserService{private UserDao userDa…

Spring实现依赖注入的几种方式

Spring实现依赖注入的几种方式 1.基于有参构造实现 <bean id"user" class"com.ccu.twj"><constructor-arg name"name" value"张三"></constructor-arg><constructor-arg name"age" value"18&quo…

依赖注入三种方式

1.构造器函数注入 分为无参构造方法和有参构造方法两种方式&#xff0c;其中有参构造方法又包含三种方式。 有参构造的三种方式&#xff1a; 下标赋值参数类型赋值参数名赋值 案例&#xff1a; User.java public class User {private String name;private String mess;pub…

spring依赖注入的三种方式以及优缺点

spring依赖注入的三种方式以及优缺点 一.依赖注入的三种方式 1.通过构造器注入。&#xff08;spring4.3之后&#xff0c;推荐使用&#xff09; 2.通过setter注入。&#xff08;spring4.3之前&#xff0c;推荐使用&#xff09; 3通过filed注入。 二.三种方式的代码示例&…

依赖注入的三种方式和循环依赖的产生

什么是循环依赖 说白了就是对象之间的依赖关系成环 例如A->B,B->C,C->A&#xff0c;并不限于对象的多少&#xff0c;最终成环就是循环依赖&#xff0c;也因此循环依赖的发生可能是十分复杂的。&#xff0c;如果使用属性注入的话&#xff0c;开发过程中甚至很难察觉。…

[Spring] IoC的理解及三种依赖注入方式

[Spring] IoC的理解及三种依赖注入方式 Spring---IoC的理解及三种依赖注入方式IoC是什么意思依赖控制反转 Spring提供的依赖注入的三种方式setter注入&#xff08;属性注入&#xff09;构造器注入p命名空间注入&#xff08;工厂方法注入&#xff09; Autowired Spring—IoC的理…

Spring依赖注入的三种方式

目录 一、变量注入&#xff08;Field Injection&#xff09; 二、构造器注入&#xff08;Constructor Injection&#xff09; 三、setter方法注入 &#xff08;Setter Injection&#xff09; 四、使用场景 Spring的依赖注入&#xff0c;我们一般使用Autowired注解来完成&am…

依赖注入的三种方式

DI(依赖注入) 注入的三种方法&#xff1a;构造器方法注入&#xff0c;set注入&#xff0c;基于注解的注入&#xff08;接口注入&#xff09; 1&#xff1a;构造器方法注入 创建一个Address类&#xff1b; public class Address {private String address;public Address() {}pu…

Pubmedy的使用教程

使用方法如下&#xff1a; 使用前先配置Sci-Hub的地址&#xff0c;如果网址不失效&#xff0c;配置一次即可 选中文章的DOI&#xff0c;右击选择Sci-Hub Search即可自动跳转到文章对应的Sci-Hub界面

Pubmedy加载时显示程序包无效的解决方案

目前谷歌应用商城已经下架Pubmedy&#xff0c;本地安装又遇到程序包无效&#xff1a;“CRX_HEADER_INVALID”。 解决方案&#xff1a; 将PubMedy.crx重命名为PubMedy.rar或者PubMedy.zip解压到要安装的位置找到扩展程序选项&#xff0c;并启用开发者选项选择加载已解压的扩展程…

细胞实验文献检索——PubMed | MedChemExpress

今天我们就以小白的课题——自噬 (Autophagy) 为例&#xff0c;给大家展示一波。这个时候给大家隆重介绍我们的——PubMed。 PubMed 提到 PubMed&#xff0c;相信大家应该都不陌生&#xff0c;它是常用的国外数据库之一&#xff0c;也是小编查找文献最喜欢的工具。自成立以来…

免费获取论文全文的方法,SCI-HUB的使用教程

很多人不在学校期间需要看文献全文&#xff0c;很多人获取文章的方式或是在网上求助或是给原作者索要。在SCI—HUB出现后&#xff0c;这些麻烦都不需要。SCI—PUB上保存了超过了4700万篇科研文献。SCI—PUB的网址 使用方法&#xff1a; 方法一、打开网页将想要论文的URL地址&…

SCI-HUB丨最新文献网址

sci-hub&#xff1a;在我们获取文献与学术论文的道路上提供了极好的便利&#xff0c;可以从中得到免费的文献下载&#xff0c;但也因为这样遭到各大出版社&#xff1a;ai思为尔&#xff0c;施普林格&#xff0c;wiley等出版社的打击与封杀&#xff0c;使得Sci-Hub在域名上不得不…

pubmed显示服务器不稳定,PubMed天天用,可是你真的用对了吗?

你是用关键词在PubMed上找论文的吗&#xff1f;如果关键词好几个&#xff0c;由于单词间的空格键存在AND命令&#xff0c;导致明明要搜的是词组&#xff0c;搜索不是被放大就是缩小&#xff0c;很难检索到合适量且关联度高的文。例如&#xff0c;你想找和肠炎与肿瘤坏死因子相关…

pubmed文献批量化下载器

1.代码如下 import time import requests import pandas as pd import osdef getArticle(PMCID,NIHMSID,DOI,title,path):print(PMCID,NIHMSID,DOI,title,path)os.chdir(path)headers {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit…

PubMed插件:分区、影响因子和即时IF一目了然,还能秒下文献(亲测有效)

Pubmed作为生物医药研究者最常用的免费文摘数据库&#xff0c;素有检索江湖上的泰山北斗之称&#xff0c;用好Pubmed&#xff0c;其他一切pubmed镜像网站都是浮云。今天小编给大家介绍一款完全免费的无需登录的pubmed插件&#xff0c;他可以解决pubmed本身不显示杂志影响因子的…

干货分享|被PubMed收录的论文,在MEDLINE和SCIE能检索到吗?

PubMed PubMed是由美国国家医学图书馆&#xff08;National Library of Medicine&#xff0c;NLM&#xff09;的国家生物技术信息中心&#xff08;National Center for Biotechnology Information&#xff0c;NCBI&#xff09;开发研制的一个医学文献网络数据库。PubMed是当今…

MEDLINE与PubMed有什么区别?检索范围包含哪些?

PubMed PubMed是由美国国家医学图书馆&#xff08;National Library of Medicine&#xff0c;NLM&#xff09;的国家生物技术信息中心&#xff08;National Center for Biotechnology Information&#xff0c;NCBI&#xff09;开发研制的一个医学文献网络数据库。 PubMed是当今…