无限背包
一个在旅途中的长者有一个最多能装M公斤的背包;
现在有n种物品,它们的重量分别是W1,W2,...,Wn,它们的价值分别为C1,C2,...,Cn;
输入n、m以及各种物品的重量和价值,求旅行者能获得最大总价值。
输入:
3 16
5 4
4 3
6 6
输出:
12
代码与01背包几乎一样,只是枚举的顺序不同而已。
01背包枚举容量时,从大到小,避免一个物品被选择多次;
无限背包枚举容量时,从小到大,允许一件物品没做选择多次。
#include <stdio.h>
int n, m, i, j, k, w, v, f[105];
int main(){
freopen("wxbag.in", "r", stdin);
scanf("%d%d", &n, &m);
for(i=1; i<=n; i++){
scanf("%d%d", &w, &v);
for(j=w; j<=m; j++){
if(f[j-w] + v > f[j]){
f[j] = f[j-w] + v;
}
}
}
printf("%d\n", f[m]);
return 0;
}
多重背包
一个在旅途中的长者有一个最多能装M公斤的背包;
现在有n种物品,它们的重量分别是W1,W2,...,Wn,价值分别为V1,V2,...,Vn,数量分别为C1,C2,...,Cn;
输入n、m以及各种物品的重量、价值和数量,求旅行者能获得最大总价值。
输入:
3 16
5 4 2
4 3 5
6 6 1
输出:
12
多重背包,是指一个物品,可以选择多次;解法可以是将一件物品拆成多件物品。
如一件物品可以选择5次,那么我们可以看成是有5件那样的物品,做5次01背包即可。
#include <stdio.h>
int n, m, i, j, k, w, v, c, f[105];
int main(){
freopen("dcbag.in", "r", stdin);
scanf("%d%d", &n, &m);
for(i=1; i<=n; i++){
scanf("%d%d%d", &w, &v, &c);
while(c--){
for(j=m; j>=w; j--){
if(f[j-w] + v > f[j]){
f[j] = f[j-w] + v;
}
}
}
}
printf("%d\n", f[m]);
return 0;
}
混合背包
有的物品只能选1次,有的物品可以选择多次,有的物品可以选择很多次……混合在一起,就是混合背包。
如多重背包中,物品的数量c很大,那就好超时了;数量很大时,应转成无限背包去做。
#include <stdio.h>
int n, m, i, j, k, w, v, c, f[105];
int main(){
freopen("dcbag.in", "r", stdin);
scanf("%d%d", &n, &m);
for(i=1; i<=n; i++){
scanf("%d%d%d", &w, &v, &c);
if(c*w >= m){
for(j=w; j<=m; j++){
if(f[j-w] + v > f[j]){
f[j] = f[j-w] + v;
}
}
}
else{
while(c--){
for(j=m; j>=w; j--){
if(f[j-w] + v > f[j]){
f[j] = f[j-w] + v;
}
}
}
}
}
printf("%d\n", f[m]);
return 0;
}
练习题
1 -- [C++一本通-动态规划]例9.12 完全背包
题目描述
设有n 种物品,每种物品有一个重量及一个价值。但每种物品的数量是无限的,同时有一个背包,最大载重量为m,今从n 种物品中选取若干件(同一种物品可以多次选取),使其重量的和小于等于m,而价值的和为最大。
输入
第1行:两个整数,m(背包容量,m<=200)和n(物品数量,n<=30);
第2至n+1行:每行两个整数Wi,Ci,表示每个物品的重量和价值。
输出
仅一行,一个数,表示最大总价值。
样例输入
10 4
2 1
3 3
4 5
7 9
样例输出
max=12
参考代码
#include<bits/stdc++.h>
using namespace std;
const int qwq = 3000;
int m,n;
int w[qwq],v[qwq];
int dp[qwq][qwq];
int main() {
cin>>m>>n;
for(int i = 1; i <= n; i++) {
cin>>w[i]>>v[i];
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
if(j < w[i]) {
dp[i][j] = dp[i-1][j];
} else {
if(dp[i - 1][j] > dp[i][j - w[i]] + v[i]) {
dp[i][j] = dp[i - 1][j];
} else {
dp[i][j] = dp[i][j - w[i]] + v[i];
}
}
}
}
cout<<"max="<<dp[n][m];
return 0;
}