1068. Find More Coins (30)

来源:互联网 发布:nba球队数据排名 编辑:程序博客网 时间:2024/06/02 21:22

    参考博客,动态规划求解,假设用 F(n, m) 表示从前 n 个硬币中挑选出能得到不超过 m 的最大和,则可以有如下递推式:

F(n, m) = max(F(n-1, m), F(n-1, m - coins[n]) + coins[n])

如果最终有 F(n, m) == m 则说明存在。

    另外,记录路径,原博客方法比较巧妙,用 path(n, m) 表示在从前 n 个硬币选出一组得到最多不超过 m 值时,是否用到了第 n 个硬币。所以,完整的路径可以从 path(n, m) 出发,一直回溯到最后一个硬币。


#include <iostream>#include <cstdio>#include <vector>#include <algorithm>using namespace std;int calc(int n, int m, vector<int>& coins, vector<vector<bool>>& path){vector<vector<int>> f(n+1, vector<int>(m+1, 0));path.resize(n+1, vector<bool>(m+1, false));for(int i = 1; i <= n; ++i){for(int j = 1; j <= m; ++j){if(j < coins[i] || f[i-1][j-coins[i]] + coins[i] < f[i-1][j]){f[i][j] = f[i-1][j];}else{f[i][j] = f[i-1][j-coins[i]] + coins[i];path[i][j] = true;}}}return f[n][m];}int main(){int n, m;scanf("%d%d", &n, &m);vector<int> coins(n+1);for(int i = 1; i <= n; ++i){scanf("%d", &coins[i]);}sort(begin(coins)+1, end(coins), greater<int>());vector<vector<bool>> path;if(m != calc(n, m, coins, path)){printf("No Solution");}else{bool first = true;while(m){while(!path[n][m]) --n;if(first) first = false;else printf(" ");printf("%d", coins[n]);m -= coins[n];--n;}}return 0;}


0 0
原创粉丝点击