问题描述
给定N个物品,每个物品有一个重量W和一个价值V.你有一个能装M重量的背包.问怎么装使得所装价值最大.每个物品只有一个.
输入格式
输入的第一行包含两个整数n, m,分别表示物品的个数和背包能装重量。
以后N行每行两个数Wi和Vi,表示物品的重量和价值
输出格式
输出1行,包含一个整数,表示最大价值。
样例输入
3 5
2 3
3 5
4 7
样例输出
8
AC代码:
//动态规划解法:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
//求容量为c的背包中放的最大价值 一共有n个物品
/*
//向容量为c的背包放入第i个物品的最大价值
①第i个物品不放进去: F(i,c) = F(i-1,c)
②第i个物品放进去: F(i,c) = v[i] + F(i-1,c-w[i])
*/
vector<vector<int> > memo;
//w和v分别是重量和价值的数组 index为物品数量标号 【0..n-1】 共有n个物品 c为背包容量
int getMaxValue( vector<int> w , vector<int> v , int index , int c ){
if( index == 0 )
return 0;
//先处理第一个物品
for( int j = 0 ; j <= c ; j ++ )
memo[0][j] = ( j>=w[0] ? v[0]:0 );
for( int i = 1 ; i < index ; i ++ ){
for( int j = 0 ; j <= c ; j ++ ){ //由于是求子问题 所以一定要从0开始
if( j >= w[i] ) //如果能放进去 则找出放和不放的大值
memo[i][j] = max( memo[i-1][j] , v[i] + memo[i-1][j-w[i]] );
else
memo[i][j] = memo[i-1][j];
}
}
return memo[index-1][c]; //
}
int main()
{
int n,m;
cin >> n >> m;
vector<int> w;
vector<int> v;
int a,b;
memo = vector<vector<int> >(n+2,vector<int>(m+2,0));
for( int i = 0 ; i < n ; i ++ ){
cin >> a >> b;
w.push_back(a);
v.push_back(b);
}
cout << getMaxValue(w,v,n,m) << endl;
return 0;
}
//w和v分别是重量和价值的数组 index为物品数量标号 【0..n-1】 共有n个物品 c为背包容量
int getMaxValue( vector<int> w , vector<int> v , int index , int c ){
if( index == 0 )
return 0;
//先处理第一个物品
for( int j = 0 ; j <= c ; j ++ )
memo[0][j] = ( j>=w[0] ? v[0]:0 );
for( int i = 1 ; i < index ; i ++ ){
for( int j = 0 ; j <= c ; j ++ ){ //由于是求子问题 所以一定要从0开始
if( j >= w[i] ) //如果能放进去 则找出放和不放的大值
memo[i][j] = max( memo[i-1][j] , v[i] + memo[i-1][j-w[i]] );
else
memo[i][j] = memo[i-1][j];
}
}
return memo[index-1][c]; //
}
int main()
{
int n,m;
cin >> n >> m;
vector<int> w;
vector<int> v;
int a,b;
memo = vector<vector<int> >(n+2,vector<int>(m+2,0));
for( int i = 0 ; i < n ; i ++ ){
cin >> a >> b;
w.push_back(a);
v.push_back(b);
}
cout << getMaxValue(w,v,n,m) << endl;
return 0;
}
注:当数组涉及到减时 如memo[index-1][c] 注意不要越界。
//记忆花搜索解法:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
//求容量为c的背包中放的最大价值 一共有n个物品
/*
//向容量为c的背包放入第i个物品的最大价值
①第i个物品不放进去: F(i,c) = F(i-1,c)
②第i个物品放进去: F(i,c) = v[i] + F(i-1,c-w[i])
*/
vector<vector<int> > memo;
vector<int> weight;
vector<int> value;
vector<int> flag;
int getMaxValue(int i, int curCapacity) {
if (i < 0 || curCapacity <= 0)
return 0;
if (memo[i][curCapacity] != -1)
return memo[i][curCapacity];
int w1 = -1;
int w2 = -1;
w1 = getMaxValue(i - 1, curCapacity); //第i个 物品不装
if (curCapacity >= weight[i])
w2 = getMaxValue(i - 1, curCapacity - weight[i]) + value[i]; //装
//如果这个物品装进去了 置标志位
if (w2 > w1) flag[i] = 1;
//如果没放进去 就是放入前一个物品后的重量
else {
i == 0 ? flag[0] = 1 : flag[i - 1] = 1; //这里要注意一下 i-1 不要越界
}
memo[i][curCapacity] = max(w1, w2);
return memo[i][curCapacity];
}
int main()
{
int n, c, wi, vi;
cin >> n >> c;
memo = vector<vector<int>>(n + 1, vector<int>(c + 1, -1));
flag = vector<int>(n, 0);
for (int i = 0; i < n; i++) {
cin >> wi >> vi;
weight.push_back(wi);
value.push_back(vi);
}
int res = getMaxValue(n - 1, c);
cout << "res = " << res << endl;
cout << "装入物品编号为:";
for (int i = 1; i < flag.size(); i++)
cout << flag[i] << " ";
cout << endl;
return 0;
}