【背包dp】输出方案路径

1 01背包输出方案

2 按字典序顺序输出所选背包物品

举个例子,输入的数据↓

bash 复制代码
N=5, V=5
1: v=2 w=3
2: v=1 w=0
3: v=1 w=0
4: v=2 w=3
5: v=1 w=5

按照逆向dp,构造出的dp数组(dpij表示体积为j时,放第i件物品的最大价值)。如下表所示,dp1V存储了n件物品,体积为V时的最大价值。搜索时,正序遍历dp数组,内层循环逆序遍历体积,如果dpi+1curV - v\[i] + wi == dpicurV),说明第i件物品有选。

体积/物品 0 1 2 3 4 5
物品1 0 5 5 8 8 11
物品2 0 5 5 8 8 8
物品3 0 5 5 8 8 8
物品4 0 5 5 8 8 8
物品5 0 5 5 5 5 5
参考代码
cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

int n, V;
int v[1005], w[1005];
int dp[1005][1005]; // dp[i][j]: 从 i 到 n,容量 j 的最大价值
bool chosen[1005];

int main(){
    cin >> n >> V;
    for(int i = 1; i <= n; i++){
        cin >> v[i] >> w[i];
    }

    // 逆序 DP
    for(int i = n; i >= 1; i--){
        for(int j = 0; j <= V; j++){
            dp[i][j] = dp[i+1][j];
            if(j >= v[i]){
                dp[i][j] = max(dp[i][j], dp[i+1][j - v[i]] + w[i]);
            }
        }
    }

    // 从前往后贪心,保证字典序最小
    int curV = V;
    for(int i = 1; i <= n; i++){
        if(curV >= v[i] && dp[i+1][curV - v[i]] + w[i] == dp[i][curV]){
            chosen[i] = true;
            curV -= v[i];
        }
    }
    for(int i = 1; i <= n; i++){
        if(chosen[i]){
            cout << i<<" ";
        }
    }
    cout << "\n";
    return 0;
}

例题2 洛谷P2066

对于编号小的尽量少分配机器,再做dp时考虑正向。搜索方案的时候逆向搜索。

参考代码
cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n, m, a[20][20], dp[20][20];
int ansk[20];

signed main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			cin >> a[i][j];
	for (int i = 1; i <= n; i++) {
		for (int j = m; j >= 1; j--) {
			dp[i][j] = dp[i - 1][j];
			for (int k = 1; k <= j; k++)
				dp[i][j] = max(dp[i][j], dp[i - 1][j - k] + a[i][k]);
		}
	}
	cout << dp[n][m] << endl;
	int curM = m;
	for (int i = n; i >= 1; i--) {
		for (int k = curM; k >= 1; k--) {
			if (dp[i][curM] == dp[i - 1][curM - k] + a[i][k]) {
				ansk[i] = k;
				curM -= k;
				break;
			}
		}
	}
	for (int i = 1; i <= n; i++)
		cout << i << " " << ansk[i] << endl;
	return 0;
}
相关推荐
朝朝辞暮i2 小时前
C++ 第 27 课:智能指针 shared_ptr
开发语言·c++·算法
by209992 小时前
学会使用std::string类,并理解其内部是如何管理字符串的详细阐述(上)
c++·笔记·字符串·类和对象·string
沙漠之主2 小时前
C++编程教学设计资料:从入门到实战的完整课程方案
java·前端·c++
朝朝辞暮i2 小时前
C++ 第 29 课:回调函数 Callback
开发语言·c++·算法
kaixin_learn_qt_ing3 小时前
C++多态实现原理
c++
无名猿3 小时前
unique_ptr 完全指南:独占所有权与零开销
c++·性能优化·内存管理·标准库·现代c++
笑鸿的学习笔记3 小时前
C++笔记之大块顺序写
java·c++·笔记
无名猿4 小时前
对象构造与析构顺序全解:声明顺序、继承链与逆序析构
c++·内存管理·调试技巧·现代c++
殷色玫瑰4 小时前
C/C++ 内存管理详解:从内存分布到 new/delete 底层原理
java·linux·c语言·c++