题目描述
Z国的货币系统包含面值1元、4元、16元、64元共计4种硬币,以及面值1024元的纸币。现在小Y使用1024元的纸币购买了一件价值为 N ( 0 < N ≤ 1024 ) N(0<N\leq1024) N(0<N≤1024)的商品,请问最少他会收到多少硬币?
输入描述
一行,包含一个数N。
输出描述
一行,包含一个数,表示最少收到的硬币数。
示例1
输入
200
输出
17
说明
花200,需要找零824块,找12个64元硬币,3个16元硬币,2个4元硬币即可。
题目分析
题目中关键信息为“最少”收到多少硬币,显然贪心问题是可以解决的。
贪心解法
贪心的思路是只考虑当前的最优,也就是尽可能的找零64面额的硬币,之后的找零尽可能使用16,然后是4、1。如此便可得到答案。
#include <iostream>
using namespace std;
int main(){
int n = 0;
cin >> n;
int change = 1024 - n;
int res = 0;
int value = 64;
while(change != 1){
res += change/value;
change = change%value;
value = value/2;
}
res = res + change;//此时change可能为0,1,2,3直接相加就行
return res;
}
动态规划
动态规划的思路是从最小的面额需要找零多少,迭代得出答案。
这个题如果不使用辅助数组,会复杂很多。给出的是使用辅助数组。
#include <iostream>
using namespace std;
int main(){
int n = 0;
cin >> n;
int change = 1024 - n;
int res = 0;
vector<int> dp(change+1,change+1);
dp[0] = 0;
dp[1] = 1;
//这种使用新的数组来辅助表达各种情况的方法,很好用
int amount[4]{1,4,16,64};
for(int i=2;i<=change;i++)
{
for(int j=0;j<4;j++)
{
if(i>=amount[j])
dp[i]=min(dp[i],dp[i-amount[j]]+1);
}
}
return dp[i];
}
总结
该题中使用贪心的方法显然是比使用动态规划的方法效率更高,也更容易想到,是一个较为简单的贪心问题。