当前位置:首页 > 题解目录 > 正文内容

【题解】找零钱—动态规划

亿万年的星光4年前 (2021-10-10)题解目录8903

给定一些人民币的面额,数量不限,要求找出金额为m元且人民币张数最少的方案。这个问题既可以是一个贪心问题也可以是一个动态规划的问题。

对于现行的人民币面额:1、2、5、10、20、50、100,我们找任何金额的零钱都可以使用贪心法求解,比如找72元 = 50 + 20 + 2,3张人民币即可实现。

但如果面额发生变化的话,则用贪心算法无法求出最优解,例如面额为1、3、6、7, 要找12元的话只能是 12 = 7 + 3 + 1 + 1必须使用4张人民币,而最优解为12 = 6 + 6,两张人民币即可。因此这种问题一般使用动态规划求解。

侧面说明一点,贪心法大家都会,动态规划就不一定了!

1、动态规划解题思路

设给定的面额为x1,x2,x3。现要求找n元零钱,假设已经找好也就是你已经拿到一叠零钱,它的张数最少且总和恰好为n nn

假设f(n)表示找n nn元钱的最少人民币张数,我们现在关注的是找的这些零钱的最后一张,它只能是

x1,x2...中的任意一张,假设最后一张为xi,那么要使总的人民币张数最少,必然要使子问题f(n-xi)最少。因此,

该状态转移方程为f(n)=min( f(n-xi) + 1)

DP:

int m[5] = {0, 1, 3, 4, 7 };
int dp(int n)
{
	if (n == 1 || n == 3 || n == 4 || n == 7)  return  1; //递归出口
	int ans = INT_MAX;  //因为求最小值,所以这里初始为最大值
	for (int i = 1; i <= 4; i++)
		if (m[i] <= n) ans = min(ans, dp(n - m[i]) + 1);
	return ans;
}

记忆化搜索DP代码如下:

int dp(int n)
{
	if (n == 1 || n == 3 || n == 4 || n == 7)  return ans[n] = 1;
	if (ans[n]) return ans[n];
	ans[n] = INT_MAX;
	for (int i = 1; i <= 4; i++)
		if (m[i] <= n) ans[n] = min(ans[n], dp(n - m[i]) + 1);
	return ans[n];
}


扫描二维码推送至手机访问。

版权声明:本文由青少年编程知识记录发布,如需转载请注明出处。

分享给朋友:

相关文章

【题解】前缀最小值

【题目描述】求一个数列的所有前缀最小值之和。即:给出长度为n的数列a[i],求出对于所有1<=i<=n,min(a[1],a[2],...,a[i])的和。由于读入较大,数列由随机种子生成...

【题解】特殊的质数肋骨

【题目描述】农民约翰母牛总是产生最好的肋骨。你能通过农民约翰和美国农业部标记在每根肋骨上的数字认出它们。农民约翰确定他卖给买方的是真正的质数肋骨,是因为从右边开始切下肋骨,每次还剩下的肋骨上的数字都组...

【题解】发工资

【题目描述】财务处的小李最近就在考虑一个问题:如果每个员工的工资额都知道,最少需要准备多少张人民币,才能在给每位员工发工资的时候都不用员工找零呢?这里假设程序猿的工资都是正整数,单位元,人民币一共有1...

【题解】流感传染

【题目描述】有一批易感人群住在网格状的宿舍区内,宿舍区为n\*n的矩阵,每个格点为一个房间,房间里可能住人,也可能空着。在第一天,有些房间里的人得了流感,以后每天,得流感的人会使其邻居传染上流感,(已...

【题解】最大子矩阵

【题目描述】已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是1 × 1)子矩阵。比如,如下4 × 4的矩阵0  -2 -7&nb...

大象喝水

【题目描述】上课的时候老师问了小蒜蒜和同学们一个问题:一只大象口渴了,要喝 20 升水才能解渴,但现在只有一个深 h 厘米,底面半径为 r厘米的小圆桶...