一个旅行者有一个最多能装 M 公斤的背包,现在有 n 件物品,它们的重量分别是W1,W2,...,Wn,它们的价值分别为C1,C2,...,Cn,求旅行者能获得最大总价值。
输入格式:
第一行:两个整数,M(背包容量,M<=200)和N(物品数量,N<=30);
第2..N+1行:每行二个整数Wi,Ci,表示每个物品的重量和价值。
输出格式:
第一行,一个数,表示最大总价值。
第二行,按从小到大输出物品编号,编号间用一个空格隔开,最后一个数后有一个空格。
输入样例:
10 4
2 1
3 3
4 5
7 9
输出样例:
12
2 4
样例说明:表示选第2,4两件物品得到最大价值12
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
int t[110]; //各个商品的体积
int v[110]; //各个商品的价值
int dp[110][1010] = {0};//代表取第i种商品,在体积为j时的最大价值***
int dp2[110][1010] = {0}; //用于寻找购买的商品,初始化都为0
int resort[110] = {0}; //用于存放结果,按要求正序或逆序输出
int T; //背包总容量
int M; //商品个数
void show(); //测试用
void KnapSackDP(int n, int T); //输出选择的商品编号
int main()
{
//输入背包容量T和商品总数M
cin >> T >> M;
for(int i = 1; i <= M; i++)
{
//输入每个商品的体积t和价值v
cin >> t[i] >> v[i];
}
for(int i = 1; i <= M; i++)
{
for(int j = T; j >= 0; j--) //从后往前是为了滚动数组做准备
{
if(t[i] > j)
{
dp[i][j] = dp[i-1][j];
}
else
{
dp[i][j] = max(dp[i-1][j],dp[i-1][j-t[i]]+v[i]);
if(dp[i][j] == dp[i-1][j-t[i]]+v[i])
{
dp2[i][j] = 1;//当他是1,就说明当前体积下,最优解里有这个商品
}
if(dp[i][j] == dp[i-1][j])
dp2[i][j] = 0;//当它是0,就说明当前体积下,最优解里没有这个商品
}
}
}
cout << dp[M][T] << endl;
KnapSackDP(M, T);
//show();
return 0;
}
void show()
{
for(int i = 1; i <= 5; i++)
{
for(int j = 0; j <= 13; j++)
cout << dp2[i][j] << ' ';
cout << endl;
}
}
//输出最优解的选择,
//商品总数n,各商品价值v,各商品体积p,总容量T
void KnapSackDP(int n, int T)
{
//从最后那个开始,减去其体积后,看上一层是1,还是0
int i = n, j = T, k = 0;
while(i)
{
//是1输出该商品,然后减去该商品的体积再看上一层
if(dp2[i][j] == 1)
{
// cout << i << ' ';
resort[k++] = i;
j -= t[i];
}
i--;
}//是0就不输出,直接看上一层
for(int m = k-1; m >=0; m--)
{
cout << resort[m] << ' ';
}
}
/*测试用例
70 3
71 100
69 1
1 2
答案:3
13 5
10 24
3 2
4 9
5 10
4 9
答案:28
13 5
3 2
4 9
5 10
4 9
10 24
*/