时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: G++;GCC;VC;JAVA
想去旅游吗?那得先准备背包!
背包用来装旅游物品,现在共n种(n<=50)旅游物品,每种物品都有体积vi,重量wi,数量ci,价值ti
(vi,wi,ci和ti都为整数)。
限制体积最多V立方厘米(V<=1000),重量最多W公斤(W<=500)。
请问你如何选择物品,使得带上的物品总价值最大,这个最大总价值为多少?
比如:
物品 体积 重量 数量 价值
编号 (立方厘米) (公斤) (个) (元)
1 30 3 10 4
2 50 8 10 5
3 10 2 10 2
4 23 5 8 3
5 130 20 5 11
若V为500,W为100,则选择物品的最大价值为72(且72=104+102+4*3:由10件物品1,10件物品3,
和4件物品4组成)。
这是一个多维且有界的背包问题,属于常规0-1背包问题的扩展问题。
第一行,物品的种类n,背包体积的限制V,背包载重量的限制W。n,V和W的范围如前所述。
接下来n行,每行为该种物品i的体积vi,重量wi,数量ci,价值ti (规定vi,wi,ci和ti都为整数)。
仅一行,为选择物品子集所能获得的最大价值。
5 500 100
30 3 10 4
50 8 10 5
10 2 10 2
23 5 8 3
130 20 5 11
72
思路同01背包,只是稍稍拓展了一下思路,没提升多少难度
01背包题如下:算法设计与分析 SCAU19185 01背包问题 C++
我们将所有状态分为两类,第一类不含第 i 件物品,第二类含第 i 件物品,取决于第 i 件物品体积是否大于当前背包所能容纳的大小以及物品重量是否大于当前背包所能容纳的大小。例如:当前背包体积最大容纳量只有5,如果物品体积为7,那么很明显装不进来,同理如果背包最大载重为10,如果第 i 件物品重量为 20,很明显装不进来;
即注意第二类只有在 v[i] <= j 和 w[i] <= k 时才存在。
v[i] 为第 i 件物品体积,w[i] 为第 i 件物品重量,背包当前体积容量为 j,重量容量为 k
很多小伙伴注意到,此题还有一个条件,那就是各种物品有数量,那么我们如何处理呢?
其实很简单,我们把其一个个处理就行,意思是比如 10 个物品甲,那么我们在录入物品数组 v[i]、 w[i]、 val[i] 时,录入十次该物品即可。
更多注释可查看下方的完整代码中,有助于理解
#include
using namespace std;
int dp[501][1001][501] = { 0 }; // 由于这题跟 01背包 相比,不仅有体积,还有重量,所以需要三维DP
/*
5 500 100
30 3 10 4
50 8 10 5
10 2 10 2
23 5 8 3
130 20 5 11
*/
int main()
{
int n, V, W;
cin >> n >> V >> W;
int i, j, k;
int vi, wi, ci, ti;
int v[1000] = { 0 }; //体积 10个物体1就有10个v,10个w,10个Val
int w[500] = { 0 }; //重量
int val[500] = { 0 };//价值
// 对于此题的数量,解题思路可以是将其拆解成多个输入,即数量是10时,记录10个该物品的体积,重量,价值进去
// p 的作用是一个指针,内容是记录当前记录到第几个物品的信息了
int p = 0;
for(int i = 1; i <= n; i++){
cin >> vi >> wi >> ci >> ti;
for(int i = 1; i <= ci; i++){
p++;
v[p] = vi;
w[p] = wi;
val[p] = ti;
}
}
// 装前 i 件物品,体积容量为 j,重量容量为 k 时的最大价值
for(i = 1; i <= p; i++) {
for(j = 1; j <= V; j++) {
for(k = 1; k <= W; k++) {
// 此时要加入的第i件物品体积如果直接大于 背包当前所能容纳的体积j,或重量大于,那么加入不了,直接取上一个物品相同容纳体积的数据
if(v[i] > j || w[i] > k) {
dp[i][j][k] = dp[i - 1][j][k];
} else {
// 能装,需进行决策是否选择第i个物品,第二个比较对象为:在减去要新加的物品体积v[i] 基础上,加上新价值看看如何
// 例如:当前容纳体积为 j=5,如果要加入体积为3的物品,那么肯定是在计算体积为2的价值基础上,再加上新的物品价值
dp[i][j][k] = max(dp[i - 1][j][k], dp[i - 1][j - v[i]][k - w[i]] + val[i]);
}
//cout << "i=" << i << " j=" << j << " " << " k=" << k << " " << dp[i][j][k] << endl;
}
}
}
cout << dp[p][V][W] << endl;
return 0;
}
对我感兴趣的小伙伴可查看以下链接