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 ...
随机推荐
- hdu5666 BestCoder Round #80
Segment Accepts: 418 Submissions: 2020 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 6553 ...
- Python中模块之logging & subprocess的讲解
subprocess & logging模块的介绍 1. subprocess 该模块替代了os.system & os.pawn*所实现的功能. 2. logging 1. 日志五大 ...
- python中int的功能简单介绍
Int的功能介绍 1. 绝对值 x.__abs__()等同于abs(x) 2. 加法 x.__add__(y)等同于x+y 3. 与运算 x.__and__(y)等同于x&y 4. 布尔运算 ...
- Axis2 webservice入门--Webservice的发布与调用
一.Webservice发布 参考 http://www.cnblogs.com/demingblog/p/3263576.html 二.webservice 调用 部分参考:http://www.c ...
- 零开始:NetCore项目权限管理系统:定义基本接口和实现
上一篇讲了基础的框架搭建 地址:http://www.cnblogs.com/fuyu-blog/p/8909779.html 这篇主要讲解SqlSugar ORM的数据库连接以及建表和接口 ...
- HashSet<T>的妙用
HashSet<int> hs = new HashSet<int>(); var ret = hs.Add(1); //ret==true var ret2 = hs.Ad ...
- ubuntu 14.04 64位 安装Opencv3.1.0 (包含opencv_contrib模块)
写在前边: 据官方说法,目前还不是太稳定的算法模块都在opencv_contrib里边,由于不稳定,所以不能在release版本里发行,只有在稳定以后才会放进release里边.但是这里边有很多我们经 ...
- 从头开始搭建一个VSCode+NetCore的项目
看这个前,先要对VS开发C#有所了解 获取作案工具 NetCore SDK https://www.microsoft.com/net/learn/get-started/windows 安装 建立工 ...
- 【python标准库模块三】Os模块和Sys模块学习
Os模块 导入os模块 import os 获取当前工作目录 os.getcwd() 切换目录,跟linux中的cd一样 os.chdir("文件夹名") 递归生成文件夹 os.m ...
- Python安装与使用的常见问题
1. Python安装问题 到Python官网下载Python最新版本 Windows x86-64 executable installer (64为操作系统选择这个) Windows x86 ex ...