团体程序设计天梯赛 L3-001 凑零钱 (30分)(0/1背包)

题目链接:

L3-001 凑零钱 (30分)

思路:

将每个硬币的面值既当作它的价值也当作它所消耗的容量,我们的目标即是在容量为m的情况下,所能得到的最大总价值能否为m
既然是求一定容量下的最大价值,那么就是经典的0/1背包问题了;
我们需要打印出最大价值的情况下所选取的所有硬币,我们只能从后往前打印,因此我们将初始的价值降序排序,从而在从后往前选取路径时先选取的是面值小的硬币;

代码:

#include<bits/stdc++.h>

using namespace std;

const int maxn = 1e4 + 5;
int n, m, w[maxn], dp[maxn], flag[maxn][maxn];

int main() {
#ifdef MyTest
	freopen("Sakura.txt", "r", stdin);
#else
	ios::sync_with_stdio(false);
	cin.tie(0);
#endif
	cin >> n >> m;
	for(int i = 0; i < n; i++) cin >> w[i];
	sort(w, w + n, greater<int>());
	for(int i = 0; i < n; i++)
		for(int j = m; j >= w[i]; j--)
			if(dp[j] <= dp[j - w[i]] + w[i]) {
				flag[i][j] = true;
				dp[j] = dp[j - w[i]] + w[i];
			}
	if(dp[m] != m) { cout << "No Solution
"; exit(0); }
	int ans = m, pos = n - 1;
	while(ans) {
		while(flag[pos][ans] == false) --pos;	
		cout << w[pos];
		ans -= w[pos--];
		if(ans) cout << ' ';
	}
	return 0;
}
原文地址:https://www.cnblogs.com/yuhan-blog/p/12308635.html