【背包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;
}
相关推荐
I_belong_to_jesus8 小时前
C++关于分支预测的优化1
开发语言·c++·算法
Rabitebla10 小时前
【Linux】进程控制(十二) 自定义 Shell(二):内建命令与进程工作目录管理
linux·c++·笔记·学习·bash
码客-ygluu15 小时前
一个通用游戏数据服务器
c++·架构
another heaven15 小时前
【C/C++ Ranges 是零开销抽象吗?拆开管道、惰性求值和编译期膨胀】
c语言·开发语言·c++
上海潭龙东海科技有限公司16 小时前
客运站管控之动态孪生技术方案(新增一屏管控模块
数据仓库·人工智能·算法·重构·动态规划
YLCHUP18 小时前
【思维&图论建模】题解:债权(debt)_图论_建模_思路转化_思维题目_C++算法竞赛
c++·笔记·算法·数学建模·贪心算法·深度优先·图论
xiaoye-duck18 小时前
《C++ 项目:手写大模型接入 SDK》会话模块整合:内存 SessionManager 与 DataManager 持久化联动
开发语言·数据库·c++·语言模型
思麟呀19 小时前
背包DP(01背包+完全背包)
c++·算法
旖旎夜光20 小时前
【C++ 基础入门】C++11 新特性(中):右值引用、移动语义与完美转发
开发语言·c++·笔记·学习
ShineWinsu20 小时前
对于Qt:QTabWidget常见属性的解析
开发语言·数据库·c++·qt·浏览器·qtabwidget·标签页