赞
踩
首先给出背包的容量,接着:
在背包的限制之内,做出抉择,选择物品填充背包,使得最终背包的质量最大。
Dp由于变化较多,没有固定模板,可以从两个方面入手分析,即:状态表示和状态计算,我们把状态设为f[i][j]
有 N 件物品和一个容量是 V的背包。每件物品只能使用一次。
第 i件物品的体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。
第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。
接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。
输出一个整数,表示最大价值。
0<N,V≤1000
0<vi,wi≤1000
4 5
1 2
2 4
3 4
4 5
8
#include<iostream> #include<algorithm> using namespace std; const int N = 1010; //物品的最大数量 int n,m; //n是物品数量,m是背包的容量 int v[N], w[N]; //v[i]是第i件物品的体积,w[i]是第i件物品的质量 int f[N][N]; //状态表示,全局变量初始化为0 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 = 0;j <= m;j ++ ) { f[i][j] = f[i - 1][j]; //只有在给定的j容量大于第i个物品的体积时,才可以放第i个物品,不然程序会错误 if(j >= v[i]) f[i][j] = max(f[i][j],f[i - 1][j - v[i]] + w[i]); } cout << f[n][m] << endl; return 0; }
#include<iostream> #include<algorithm> using namespace std; const int N = 1010; //物品的最大数量 int n,m; //n是物品数量,m是背包的容量 int v[N], w[N]; //v[i]是第i件物品的体积,w[i]是第i件物品的质量 int f[N]; //状态表示,全局变量初始化为0 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
4 5
1 2
2 4
3 4
4 5
10
#include<iostream> #include<algorithm> using namespace std; const int N = 1010; //物品的最大数量 int n,m; //n是物品数量,m是背包的容量 int v[N], w[N]; //v[i]是第i件物品的体积,w[i]是第i件物品的质量 int f[N][N]; //状态表示,全局变量初始化为0 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 = 0;j <= m;j ++ ) for(int k = 0;k * v[i] <= j;k ++ ) f[i][j] = max(f[i][j],f[i-1][j - k * v[i]] + k * w[i]); //由于k从0开始,所以已经包含了f[i-1][j],不需要单独列出 cout << f[n][m] << endl; return 0; }
#include<iostream> #include<algorithm> using namespace std; const int N = 1010; //物品的最大数量 int n,m; //n是物品数量,m是背包的容量 int v[N], w[N]; //v[i]是第i件物品的体积,w[i]是第i件物品的质量 int f[N]; //状态表示,全局变量初始化为0 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 = 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。
求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。
第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。
接下来有 N 行,每行三个整数 vi,wi,si,用空格隔开,分别表示第 i 种物品的体积、价值和数量。
输出一个整数,表示最大价值。
0<N≤1000
0<V≤2000
0<vi,wi,si≤2000
4 5
1 2 3
2 4 1
3 4 3
4 5 2
10
#include<iostream> #include<algorithm> using namespace std; const int N = 1010; //物品的最大数量 int n,m; //n是物品数量,m是背包的容量 int v[N], w[N],s[N]; //v[i]是第i件物品的体积,w[i]是第i件物品的质量,s[i]是第i件物品有多少件 int f[N][N]; //状态表示,全局变量初始化为0 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 * v[i] <= j && k <= s[i];k ++ ) f[i][j] = max(f[i][j],f[i-1][j - k * v[i]] + k * w[i]); //由于k从0开始,所以已经包含了f[i-1][j],不需要单独列出 cout << f[n][m] << endl; return 0; }
#include<iostream> #include<algorithm> using namespace std; const int N = 2500; //物品的最大数量,N+logw int n,m; //n是物品数量,m是背包的容量 int v[N], w[N]; //v[i]是第i件物品的体积,w[i]是第i件物品的质量 int f[N]; //状态表示,全局变量初始化为0 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(k <= s) { cnt ++ ; v[cnt] = a * k; w[cnt] = b * k; s -= k; k *= 2; } if(s>0) //防止s刚好用完 { cnt ++; v[cnt] = a * s; w[cnt] = b * s; } } n = cnt; //此时物品相当于有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; }
有 N 组物品和一个容量是 V 的背包。
每组物品有若干个,同一组内的物品最多只能选一个。
每件物品的体积是 vij,价值是 wij,其中 i 是组号,j 是组内编号。
求解将哪些物品装入背包,可使物品总体积不超过背包容量,且总价值最大。
输出最大价值。
第一行有两个整数 N,V,用空格隔开,分别表示物品组数和背包容量。
接下来有 N 组数据:
输出一个整数,表示最大价值。
0<N,V≤100
0<Si≤100
0<vij,wij≤100
3 5
2
1 2
2 4
1
3 4
1
4 5
8
#include<iostream> #include<algorithm> using namespace std; const int N = 110; //物品的最大数量 int n,m; //n是物品数量,m是背包的容量 int v[N][N], w[N][N],s[N]; //v[i][j]是第i组第j件物品的体积,w[i][j]是第i组第j件物品的质量,s[i]是第i组有多少个物品 int f[N]; //状态表示,全局变量初始化为0 int main() { cin >> n >> m; for(int i = 1;i <= n;i ++ ) { cin >> s[i]; //s[i]是第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] && v[i][k] <= j;k ++ ) f[j] = max(f[j],f[j - v[i][k]] + w[i][k]); cout << f[m] << endl; return 0; }
从上例我们可以看到,01背包问题、多重背包问题、分组背包问题其实十分相似,多重背包优化是进行二进制操作拆包后的01背包优化,分组背包优化是多了一个循环的01背包优化,第二个循环都需要倒置。而完全背包问题相较于01背包问题优化,唯一的区别在于第二个循环是否倒置。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。