1068. Find More Coins (30)
题目如下:
Eva loves to collect coins from all over the universe, including some other planets like Mars. One day she visited a universal shopping mall which could accept all kinds of coins as payments. However, there was a special requirement of the payment: for each
bill, she must pay the exact amount. Since she has as many as 104 coins with her, she definitely needs your help. You are supposed to tell her, for any given amount of money, whether or not she can find some coins to pay for
it.
Input Specification:
Each input file contains one test case. For each case, the first line contains 2 positive numbers: N (<=104, the total number of coins) and M(<=102, the amount of money Eva has to pay). The second
line contains N face values of the coins, which are all positive numbers. All the numbers in a line are separated by a space.
Output Specification:
For each test case, print in one line the face values V1 <= V2 <= ... <= Vk such that V1 + V2 +
... + Vk = M. All the numbers must be separated by a space, and there must be no extra space at the end of the line. If such a solution is not unique, output the smallest sequence. If there is no solution, output "No Solution"
instead.
Note: sequence {A[1], A[2], ...} is said to be "smaller" than sequence {B[1], B[2], ...} if there exists k >= 1 such that A[i]=B[i] for all i < k, and A[k] < B[k].
Sample Input 1:
8 9
5 9 8 7 2 3 4 1
Sample Output 1:
1 3 5
Sample Input 2:
4 8
7 2 4 3
Sample Output 2:
No Solution
题目要求从一系列硬币中找出最小的、满足给定面值和的硬币序列,这属于典型的背包问题,问题的难点在于输出最小序列。
【如何找到这样的序列】
我们设f(i,j)表示从前i个硬币中选出的面值不大于j的最大的面值和,设硬币序列中第i个硬币的面值为c[i],则f(i,j)的计算可以分为两种情况递推考虑:
每个硬币都有放入和不放入两种情况。
①放入第i个硬币,即f(i-1,j - c[i]) + c[i]。
②不放入第i个硬币,即f(i-1,j)。
要保证面值最大,应该选择二者中的较大者,因此递推式如下:
因此我们只要从i=1~N,分别解决j=1~M的问题,便可以得到不超过M的最大面值,通过判断f(N,M),如果它=M,说明能够找到这样的序列,否则说明找不到,因为它是不超过M的,从所有硬币中能组合出的最大的和。
【如何使序列最小】
接下来我们解决序列最小的问题,我们这样考虑,每当加入一个c[i],序列中就会多一个元素,如果我们让硬币按照降序排列,这样每一次加入c[i],都相当于加入了一个更小的序列头,例如现在的序列是{5,3,2},因为是降序,c[i]≤2,因此只要加入c[i],序列会编程{5,3,2,c[i]},这个序列必定变小,因此我们应该记录下所有加入c[i]时的下标,最后根据这些下标回溯,即可得到最小的序列。
以下代码来着tiantangrenjian,感谢他提供的解法;关于最小序列的找法,学习自gzxcyy,感谢他的详尽分析。
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std; #define MAXTOTAL 10001
#define MAXAMOUNT 101 int f[MAXTOTAL][MAXAMOUNT]; //f[n][m]表示 前n个数中 得出的 最接近m 的值
bool has[MAXTOTAL][MAXAMOUNT]; //has[n][m]表示在前n个数中得出最接近m的值时 是否用到c[n]
int* c = NULL; int calcClosestSum(int n,int m)
{
memset(f,0,sizeof(int)*MAXTOTAL*MAXAMOUNT);
memset(has,false,sizeof(bool)*MAXTOTAL*MAXAMOUNT);
int i,j;
int sec; // 表示放入c[i]后的值
for(i=1;i<n+1;i++)
{
for(j=1;j<=m;j++)
{
if(j-c[i]<0) sec=0; // 如果不满足小于等于j,则说明放入后是非法值,可以设其为0,表示面值无效。
else sec = f[i-1][j-c[i]]+c[i]; // 正常情况下计算放入c[i]的值。
if(f[i-1][j] > sec)
{
f[i][j]=f[i-1][j];
}else
{
f[i][j]=sec;
has[i][j]=true; //用到c[i]了 设has[i][j]为true
}
}
}
return f[n][m];
} bool cmp(const int& A,const int& B)
{
return A>B;
} int main()
{
int n,m;
cin>>n>>m;
c = new int[n+1];
memset(c,0,sizeof(int)*(n+1)); int i;
for(i=0;i<n;i++)
{
cin>>c[i+1];
}
sort(&c[1],&c[n+1],cmp); //从大到小排序 int res = calcClosestSum(n,m);
if(res==m) //有解
{
vector<int> v;
while(m)
{
while(!has[n][m])
n--;
v.push_back(c[n]);
m = m - c[n];
n--;
}
for(i=0;i<v.size()-1;i++)
cout<<v[i]<<' ';
cout<<v[i]<<endl;
}else //无解
cout<<"No Solution"<<endl;
return 0;
}
1068. Find More Coins (30)的更多相关文章
- PAT 甲级 1068 Find More Coins (30 分) (dp,01背包问题记录最佳选择方案)***
1068 Find More Coins (30 分) Eva loves to collect coins from all over the universe, including some ...
- PAT甲题题解-1068. Find More Coins (30)-dp,01背包
一开始没多想,虽然注意到数据N<=10^4的范围,想PAT的应该不会超时吧,就理所当然地用dfs做了,结果最后一组真的超时了.剪枝啥的还是过不了,就意识到肯定不是用dfs做了.直到看到别人说用0 ...
- 1068 Find More Coins (30)(30 分)
Eva loves to collect coins from all over the universe, including some other planets like Mars. One d ...
- 1068 Find More Coins (30分)(dp)
Eva loves to collect coins from all over the universe, including some other planets like Mars. One d ...
- PAT (Advanced Level) 1068. Find More Coins (30)
01背包路径输出. 保证字典序最小:从大到小做背包. #include<cstdio> #include<cstring> #include<cmath> #inc ...
- 【PAT甲级】1068 Find More Coins (30 分)(背包/DP)
题意: 输入两个正整数N和M(N<=10000,M<=10000),接着输入N个正整数.输出最小的序列满足序列和为M. AAAAAccepted code: #define HAVE_ST ...
- PAT 1068 Find More Coins[dp][难]
1068 Find More Coins (30)(30 分) Eva loves to collect coins from all over the universe, including som ...
- PAT 甲级 1068 Find More Coins(0,1背包)
1068. Find More Coins (30) 时间限制 150 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Eva l ...
- pat1068. Find More Coins (30)
1068. Find More Coins (30) 时间限制 150 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Eva l ...
随机推荐
- Frame buffer分析 - fbmem.c【转】
转自:http://www.cnblogs.com/armlinux/archive/2012/03/01/2396753.html 45 struct fb_info *registered_fb[ ...
- Saltstack基础
salt介绍 salt简单介绍 一个基础平台管理工具 一个配置管理系统,能够维护预定义状态的远程节点 一个分布式远程执行系统,用来在远程节点上执行命令和查询数据 salt的核心功能 使命令发送到远程系 ...
- 服务器使用nginx做代理,通过HttpServletRequest获取请求用户真实IP地址
首先,在nginx配置中添加如下配置 server { listen ; server_name www.wenki.info; #要访问的域名 charset utf8; location / { ...
- Python中模块之re的功能介绍
re模块的功能介绍 1. 方法 match 从开头开始查找 方法:re.match(pattern,string,flags=0) 返回值:<class '_sre.SRE_Match'> ...
- 【js-xlsx和file-saver插件】前端导出数据到excel
最近在做项目,前端进行处理数据,导出excel中,还是遇到不少问题,这里将其进行总结一下,博主是vue框架开发,借用file-saver和xlsx插件进行导出excel,我们来看下代码和效果.地址链接 ...
- 阿里Java研发工程师实习面经
十分幸运 拿到阿里云的offer,感谢周围无数人对我的支持和鼓励,所以写篇面经希望可以帮助大家. 面试中,运气占很大一部分的,所以你们若是没有通过,一定不要气馁,继续加油. 每个努力的人 都值得钦佩, ...
- 自定义shell终端提示符及颜色即修改 PS1文件 (以Centos为例)
Linux修改Shell命令提示符及颜色 1. Linux登录过程中加载配置文件顺序: /etc/profile → /etc/profile.d/*.sh → ~/.bash_profile → ~ ...
- idea-JSP out.println报错问题
<%! out.println("xxxx");%> 上面是错误的,<%!%>是声明变量是使用,而不是进行逻辑输出! <% out.println(x ...
- JVM Class详解之一
首先看Class中包含哪些信息简单的说所有Java文件中有的信息class文件都有,编译器帮我们将java文件转化成了JVM能看懂的class格式而已 Class 概述 Class文件是一组以8位字节 ...
- 初识RabbitMQ系列之二:下载安装
一:Erlang安装 因为RabbitMQ 是Erlang语言开发的,所以首先要装上Erlang的环境 1)下载Erlang 下载官网:http://www.erlang.org/downloa ...