作者有话说
写这篇题解不是因为它有多难,只是因为本人太菜了,以此来警示自己,虽然还没找到合适的提高算法能力的手段,但是至少不能消极态度,熬夜写这篇题解,希望未来的我看到后能引以为戒
解题思路
这个题第一眼就是动态规划,高高兴兴的没发现数据范围到1e9
写完以后盯着没过的样例愣住了,愣了一个半小时(菜的我无地自容)
考完以后看着这5个面值有了想法
正式开始
首先这个数据肯定是想让我们一下算出来的
通过观察,我们发现,1、3、6、10、15,这5个看起来没什么关系的数字实际上他们的最小公倍数是30,也就是说我们完全可以把金额拆成好多个30来解决,因为30的最佳方案一定是两枚15的硬币
想到这里,呆呆的我又开始写了贪心,结果依然是没有过
问题就在这了,虽然可以拆成好多30,但是十有八九这个数字不能被30整除,所以一定会空出来一个不足30的数字
30的部分可以用15面值的直接解决,那不足30的呢
还记得我开头说的动态规划吗,没错,如果数据范围到30就完全没问题了
所以我们只需要提前准备好一个30以内所有情况的答案,然后根据上述所言直接出答案即可。
看代码大家就很容易明白了
总代码
#include<bits/stdc++.h>
using namespace std;
const int num[] = {1,3,6,10,15};
int Mi[31];
int t,o;
void init()
{
memset(Mi,0x3f,sizeof Mi);
Mi[0] = 0;
for(int i=0;i<5;i++){
for(int j=num[i];j<31;j++){
Mi[j] = min(Mi[j],Mi[j-num[i]] + 1);
}
}
}
int main()
{
init();
cin >> t;
while (t--){
cin >> o;
int num = (o/15 == 0 ? 0 : o/15-1);
o -= num * 15;
cout << num + Mi[o] << endl;
}
return 0;
}
结语
临时起意,如果题解有帮助那是我的荣幸,我希望我能领悟到算法的学习,能让我觉得自己没那么菜了