具体题目描述可以见链接[www.acwing.com/problem/con…]. 本题要求输出具体的方案,由于最优背包的方案数可以是很多种,这题要求输出字典序最小的方案。
主要思路:要求解具体的方案首先的用2维矩阵去解背包,而不能用优化后的一维。因为要得到第i件物品是否放进背包中了,需要比较f[i][j]和f[i - 1][j]以及f[i - 1][j - w[i]] + v[i]的值,如果是前者表示第i件物品没有放入背包,如果是后者则是放进了背包,如果都相等则两种方案都会达到最优,这时候需要选出字典序最小的方案。为了选出字典序最小的方案,我们就不能从后往前选,而常规的解法使得只能从后往前选。要想使得可以从后往前选,那么可以在递推解背包的时候i从大到小去填写f[i][j]。
#include <iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 1010;
int f[N][N];
int w[N];
int v[N];
int main()
{
/*
输入:
4 5
1 2
2 4
3 4
4 6
*/
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> w[i] >> v[i];
}
for (int i = n; i >= 1; i--) {
for (int j = 0; j <= m; j++) {
f[i][j] = f[i + 1][j];
if (j >= w[i]) {
f[i][j] = max(f[i][j], f[i + 1][j - w[i]] + v[i]);
}
}
}
int vol = m;
for (int i = 1; i <= n; i++) {
if (vol - w[i] >= 0 && f[i][vol] == f[i + 1][vol - w[i]] + v[i]) {
cout << i << " ";
vol -= w[i];
}
}
cout << endl;
//cout << f[1][m] << endl;
system("pause");
}