POJ 硬币

1|0题目描述

宇航员 Bob 有一天来到火星上,他有收集硬币的习惯,于是他将火星上所有面值的硬币都收集起来了,一共有  种,每种只有一个:面值分别为 a1,a2,…,an。Bob 在机场看到了一个特别喜欢的礼物,想买来送给朋友 Alice,这个礼物的价格是 X元。Bob 很想知道为了买这个礼物他的哪些硬币是必须被使用的,即Bob 必须放弃收集好的哪些硬币种类。飞机场不提供找零,只接受恰好 X 元。

2|0输入

第一行包含两个正整数 n 和 x (1≤n≤200,1≤x≤10000)(1n200,1x10000)。

第二行从小到大为 n 个正整数 a1,a2,a3,…,an (1≤ai≤10000).

3|0输出

第一行是一个整数,即有多少种硬币是必须被使用的。 第二行是这些必须使用的硬币的面值(从小到大排列)。

4|0输入输出样例

4|1样例输入 #1

5 18 1 2 3 5 10

4|2样例输出 #1

2 5 10

5|0提示

输入数据将保证给定面值的硬币中至少有一种组合能恰好能够支付 X 元。 如果不存在必须被使用的硬币,则第一行输出 0,第二行输出空行。

复制代码
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int n,res,a[N],f[N],ans[N],x,g[N];//f数组是储存i元时的所有方案数,g数组是去掉a[i]的时候的方案总数 int main() { cin>>n>>x; for(int i=0;i<n;i++) cin>>a[i]; f[0]=1;//初始化 for(int i=0;i<n;i++) for(int j=x;j>=a[i];j--) f[j]+=f[j-a[i]];//0-1背包查找方案总数 for(int i=0;i<n;i++) { memset(g,0,sizeof g); for(int j=0;j<=x;j++) if(j>=a[i]) g[j]=f[j]-g[j-a[i]]; //这里我很迷,详细说一下,g[j]是j元是没有a[i]的情况,f[j]是有a[i]的总数 //为什么要减去g而不是f,可以这样想,如果j大一点,此时的j是没有a[i]的方案了 //但是j-a[i]呢?j-a[i]元还是会有a[i],所以必须是减去g,g中永远没有a[i]的参与 else g[j]=f[j];//如果没有a[i].那就相等 if(g[x]==0) ans[res++]=a[i];//如果x的方案是0,那就不是必须的 } cout<<res<<endl; for(int i=0;i<res;i++) cout<<ans[i]<<" "; return 0; }
复制代码

 


__EOF__

本文作者Sakurajimamai
本文链接https://www.cnblogs.com/o-Sakurajimamai-o/p/17463508.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   o-Sakurajimamai-o  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
-- --
点击右上角即可分享
微信分享提示