1. 程式人生 > 其它 >揹包記錄路徑

揹包記錄路徑

題意:
總公司擁有M臺 相同 的高效裝置,準備分給下屬的N個分公司。
各分公司若獲得這些裝置,可以為國家提供一定的盈利。盈利與分配的裝置數量有關。
問:如何分配這M臺裝置才能使國家得到的盈利最大?
求出最大盈利值。
分配原則:每個公司有權獲得任意數目的裝置,但總檯數不超過裝置數M。

  • 我們把第\(i\)件物品分配到\(j\)件物品時花費定位\(j\),其價值就是\(a_{ij}\)
  • 可以看作一個分組揹包的問題,每次從\(i\)組內選擇一個物品即可
  • 記錄路徑時,僅需要記錄一下在第\(i\)個物品已裝容量為\(j\)時的轉移答案即可
  • 輸出答案,遞迴輸出路徑即可

\(c11\) 書寫遞迴匿名函式
function<返回型別(引數型別,...,引數型別)> 函式名 = [&](引數型別 引數名稱,...)

#include <bits/stdc++.h>

using namespace std;

int main() {
	int n,m; cin >> n >> m;
	vector<vector<int> >a(n + 1,vector<int>(m + 1)),pre(n + 1,vector<int>(m + 1));
	vector<int>dp(m + 1);
	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 >= 0;j --) {
			for(int k = 0;k <= m;k ++) {
				if(j < k) continue;
				if(dp[j] < dp[j - k] + a[i][k]) {
					dp[j] = dp[j - k] + a[i][k];
					pre[i][j] = k;
				}
			}
		}
	}
	cout << dp[m] << '\n';
	function<void(int,int)> output = [&](int x,int y) {
		if(x == 0) return ;
		int now = pre[x][y];
		output(x - 1,y - now);
		cout << x << ' ' << now << '\n';
	};
	output(n,m);
	return 0;
}