[UVA - 624] CD (记录路径的01背包)

链接

https://vjudge.net/problem/UVA-624

题意

n n n个数字,每个数字使用一次,求不超过 m m m的最大和为多少,并把组成这个最大和的数字输出出来;

分析

  这是一个01背包,背包容积为 m m m,物品为数字,体积和价值均为数字大小;这里需要记录路径,方法很多,如果相邻两个阶段之间发生了转移(选取了该物品,就说明使用了该物品,从最后一个阶段向前找);

代码
#include <functional>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <set>
#include <map>

#define INF 0x7f7f7f7f
#define MAXN 100005
#define N 200005
#define P 2
#define MOD 99991

typedef long long ll;

namespace fastIO {
	//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<22, stdin), p1 == p2) ? EOF : *p1++)
	//char buf[(1 << 22)], *p1 = buf, *p2 = buf;
	inline int read() {
		char c = getchar(); int x = 0, f = 1;
		while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
		while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
		return x * f;
	}
}

using namespace fastIO;
using namespace std;

int n, m, dp[30][10004], a[10005];

int main() {
	while (cin >> m >> n) {
		for (int i = 1; i <= n; i++)
			cin >> a[i];
		memset(dp, 0, sizeof(dp));
		for (int i = 1; i <= n; i++)
			for (int j = m; j >= 0; j--) {
				if (j >= a[i])dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - a[i]] + a[i]);
				else dp[i][j] = dp[i - 1][j];
			}
		int k = m;
		vector<int>vec;
		for (int i = n; i > 0; i--)
			if (k >= a[i] && dp[i][k] == dp[i - 1][k - a[i]] + a[i]) {
				k -= a[i];
				vec.push_back(a[i]);
			}
		for (int i = vec.size() - 1; i >= 0; i--)
			cout << vec[i] << " ";
		cout << "sum:" << dp[n][m] << endl;
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值