问题描述:
解法:
因为求具体的方案,我们就不能采取之前滚动数组优化版本的 01背包 ,因为这样会损失一些具体方案
因为要求字典序最小,那么我们肯定采取贪心策略(能选序号小的就选序号小的)
我们如果从前往后遍历所有的物品,那么最后 dp[n][m] 就是最后答案,那我们就得从后往前遍历才可以求的具体方案 ,但是这样所求的是字典序最大的
所以我们应该反一下,从后往前去遍历所有物品,这样dp[1][m]就是最后答案,那么我们就从前往后遍历就可以求具体方案,这样求的是字典序最小的
int n,m; int dp[1010][1010],v[1010],w[1010]; int main() { cin >> n >> m; for (int i = 1;i <= n;i++) cin >> v[i] >> w[i]; for (int i = n;i >= 1;i--) { for (int j = 0;j <= m;j++) { dp[i][j] = dp[i+1][j]; if (j >= v[i]) dp[i][j] = std::max(dp[i][j],dp[i+1][j-v[i]]+w[i]); } } int vol = m; for (int i = 1;i <= n;i++) { if (vol-v[i] >= 0 && dp[i][vol] == dp[i+1][vol-v[i]]+w[i]) { cout << i << " "; vol -= v[i]; } } return 0; }