测评会员优惠活动进行中 · 开通 VIP,有效期内测评不限次 VIP 优惠中 · 测评不限次 立即查看

A31424. 凑零钱

填空题 较难

题目描述

凑零钱

题目描述
韩梅梅喜欢满宇宙到处逛街。现在她逛到了一家火星店里,发现这家店有个特别的规矩:你可以用任何星球的硬币付钱,但是绝不找零,当然也不能欠债。韩梅梅手边有 104 枚来自各个星球的硬币,需要请你帮她盘算一下,是否可能精确凑出要付的款额。

输入格式
输入第一行给出两个正整数:N(<=104)是硬币的总个数,M(<=102)是韩梅梅要付的款额。第二行给出N枚硬币的正整数面值。数字间以空格分隔。

输出格式
在一行中输出硬币的面值 V1 <= V2 <= ... <= Vk,满足条件 V1 + V2 + ... + Vk = M。数字间以1个空格分隔,行首尾不得有多余空格。若解不唯一,则输出最小序列。若无解,则输出“No Solution”。

注:我们说序列{A[1], A[2], ...}比{B[1], B[2], ...}“小”,是指存在 k >= 1 使得 A[i]=B[i] 对所有 i < k 成立,并且 A[k] < B[k]。

输入样例1

8 9
5 9 8 7 2 3 4 1

输出样例1

1 3 5

输入样例2

4 8
7 2 4 3

输出样例2

 No Solution

参考答案

// 标准的背包问题 // 需要将硬币从大到小排序,因为题目要求序列小的,所以逆序遍历时需要从小的硬币开始遍历 // 需要用path数组将路径记录下来 #include <iostream> #include <vector> #include <algorithm> using namespace std; int M; int N; vector<int> coin; int dp[101]; int path[10001][101]; int cmp(int a,int b) { return a > b; } int main() { //freopen("data.txt", "r", stdin); cin >> N >> M; for (int i = 0; i < N; i++) { int temp; cin >> temp; coin.push_back(temp); } // 将硬币从小到大排序 sort(coin.begin(), coin.end(),cmp); // 动态规划,用path将路径记录下来 for (int i = 0; i < N; i++) { for (int j = M; j >= coin[i]; j--) { if (dp[j] <= dp[j - coin[i]] + coin[i]) { path[i][j] = 1; dp[j] = dp[j - coin[i]] + coin[i]; } } } // 从[N-1][M]开始倒着输出 if (dp[M] != M) { cout << "No Solution" << endl; } else { int j = M; int i = N - 1; while (j > 0) { if (path[i][j] == 1) { if (j != M) { cout << " "; } cout << coin[i]; j -= coin[i]; } i--; } } return 0; }
上一题 下一题