PAT L3-001 凑零钱(01背包(布尔背包)+记录路径)
2018-03-23 23:26
253 查看
L3-001. 凑零钱
时间限制:200 ms内存限制:65536 kB
代码长度限制:8000 B
判题程序:Standard
作者:陈越
韩梅梅喜欢满宇宙到处逛街。现在她逛到了一家火星店里,发现这家店有个特别的规矩:你可以用任何星球的硬币付钱,但是绝不找零,当然也不能欠债。韩梅梅手边有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 95 9 8 7 2 3 4 1
输出样例1:
1 3 5输入样例2:
4 87 2 4 3
输出样例2:
No Solution问题分析
学长和窝说这是01背包的变种布尔背包…….题意:给n个硬币,问能否组成价值m。
那该怎么设计状态呢?
我感觉就是01背包的思想。可以这样,第i个硬币能否组成m,如果第i个硬币可以组成m,那么状态dp[j-coin[i]肯定就为true,否则为false,即表示当前硬币不可达m。如果选第i个,那么问题就变成i-1个硬币组成v-coin[i]的问题,不选就是i-1个硬币组成v的问题。边界状态肯定是硬币价值为0啦,0对于m一定是可达的,所以要初始dp[0] = true;所以状态转移方程为
dp[i][j] = dp[i-1][j] | dp[i-1][j-coin[i]]; 或者简化为一维,
dp[j] = dp[j] | dp[j-coin[i]]; (0 <= i <= n-1, 0 <= j <= m)
剩下的就是路径记录问题了,只要记住当前状态是由哪个状态转移过来的即可,输出coin[i]
ok,接下来是AC code(^_^)
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; const int N = 1e4+3,M = 400; bool path [M],dp ; int coin ; bool cmp(int a,int b){ return a>b; } int main() { int n,m; cin>>n>>m; for(int i = 0; i < n; ++i){ cin>>coin[i]; } dp[0] = true; //m+0一定还可以组成m,即0这个数可达(边界状态) sort(coin,coin+n,cmp); //这里我们从大到小排序,方便输出,到后面如果有更小的方案会覆盖 for(int i = 0; i < n; ++i){ for(int j = m; j >= coin[i]; j--){ // dp[j] = dp[j]|dp[j-coin[i]]; if(dp[j-coin[i]]){ // 如果当前选择当前硬币可组成m dp[j] = true; path[i][j] = true; //记录路径 } } } if(dp[m]==false) cout<<"No Solution"<<endl; else{ int i = n-1, j = m, flag = 0; while (i>=0&&j>=0){ if(path[i][j]){ //当前状态可选 if(flag==0) { printf("%d",coin[i]); flag = 1;} else printf(" %d",coin[i]); j -= coin[i]; //要清楚当前状态是怎么转移过来的 } i--; } puts(""); } return 0; }
相关文章推荐
- PAT L3-001. 凑零钱(背包&路径记录)
- L3-001. 凑零钱 01背包 满包问题+记录路径
- L3-001. 凑零钱 - 【01背包 + 记录路径 + 裸裸裸题】
- PAT L3-001. 凑零钱((背包&路径记录)
- CCCC 题目集 L3 001 凑零钱 【背包 + 记录路径 + 思维】
- L3-001. 凑零钱(背包dp,输出路径)
- L3-001. 凑零钱 (背包输出路径)
- zoj2156Charlie's Change 多重背包可行性问题+记录路径
- 记录路径的背包问题
- POJ - 1787 完全背包,记录路径
- PAT 5-24 Find More Coins 背包记录路径
- PAT L2-001. 紧急救援 Dijkstra+权值+路径记录
- L3-001. 凑零钱 (01背包)@
- poj 1787 Charlie's Change(完全背包 或 多重背包 记录路径)
- poj 1787 多重背包记录路径
- poj 1787 背包+记录路径
- PAT L2-001. 紧急救援 Dijkstra+权值+路径记录
- CCCC-GPLT L3-001. 凑零钱 01背包满包
- CodeForces - 864E Fire 背包+记录路径
- POJ 1787 - Charlie's Change(完全背包+路径记录)