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 ...
随机推荐
- [HEOI 2016] seq
题解: 发现多决策且明显无后效性,果断dp,那么转移方程F[i]=F[j]+1 设R[I]为改变之后的最大值,L[i]为改变之后的最小值 由于只能改变一个元素 所以转移的条件是 (j<i &am ...
- hdu 4288 离线线段树+间隔求和
Coder Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Su ...
- ORACLE 触发器 基础
--触发器--语法 CREATE OR REPLACE TRIGGER TRIGGER_NAME AFTER|BEFORE|INSTEAD OF [INSERT][OR UPDATE [OF COLU ...
- Linux命令-关机命令详解
关机命令:1.halt 立刻关机 2.poweroff 立刻关机 3.shutdown -h now 立刻关机(root用户使用) 4.shutdown -h 10 10分钟后自动关机 如果是通过sh ...
- 获取X天后的日期
import java.util.Calendar; import java.util.Date; public class main { public static void main(String ...
- dnc开源梦之队2018 开源项目精选集
dnc开源梦之队2018 dnc开源项目选择标准 dnc = .NET Core.dotnet core 1.支持dnc 2.x,Github star数量100以上,最近2月活跃更新 2.轻量级.示 ...
- day04 Java Web 开发入门
day04 Java Web 开发入门 1. web 开发相关介绍 2. web 服务器 3. Tomcat服务器启动的问题 4. Tomcat目录结构 5. Web应用程序(虚拟目录映射,缺省web ...
- webstorm2017破解
选择"license server" 输入:http://idea.imsxm.com/ 2017支持vue了
- 最小费用最大流(luogu P3381 【模板】最小费用最大流)
题目链接 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S. ...
- PTA中如何出Java题目?
PTA中如何出Java题目? 很多第一次出题的老师,不知道Java在PTA中是如何处理输入的.写一篇文章供大家参考.比如以下这样的一个题目: 从控制台读入两个数,然后将其相加输出. 对于该题可以有如下 ...