您的位置:首页 > 编程语言

简单编程题目连载(四)——找零钱

2017-01-15 11:48 218 查看
经典动态规划题目的暴力求解方法

题目:

有数组penny,penny中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim(小于等于1000)代表要找的钱数,求换钱有多少种方法。

给定数组penny及它的大小(小于等于50),同时给定一个整数aim,请返回有多少种方法可以凑成aim。

测试样例:

输入:

[1,2,4],3,3

输出:

返回:2

这是一道非常经典的动态规划题目,但是直接使用动态规划求解会让初学者很不理解其中的原理,所以将这道题目分别使用暴力搜索方法,记忆搜索方法,动态规划方法以及继续化简后的动态规划方法。这次先来进行最简单的暴力求解方法。

思路是这样的:

使用0张penny[0]面值,用后续面值凑够整数aim的方法有A0种。

使用1张penny[0]面值,用后续面值凑够整数aim的方法有A1种。

使用2张penny[0]面值,用后续面值凑够整数aim的方法有A2种。

使用3张penny[0]面值,用后续面值凑够整数aim的方法有A3种。



使用N张penny[0]面值(N*penny[1]<=aim),用后续面值凑够整数aim的方法有An种。

而每一个A种方法都是进行递归求解,即就是使用0张penny[0]面值,使用0张penny[1]面值,用后续面值凑够整数aim的方法有B0种。以此类推。一个标准的递归过程,递归基为当达到目标aim,或超过目标aim。

以下为代码

//penny为待使用数组,n为数组长度,aim为凑整目标数额
public int countWays(int[] penny,int n,int aim){
//当数组为空或者输入数组长度非法或者目标数额小于等于0时,没有结果,直接返回即可
if(penny == null || n <= 0 || aim <= 0){
return 0;
}
//index从0开始,即从第一张面值起开始计算循环递归
res(penny,0,aim);
}
//本函数执行递归操作。penny为待使用数组,index为待使用面额(数组下标),aim为后续每次需要到达的目标金额
publi
4000
c int res(int[] penny,int index,int aim){
//定义结果数变量,初始化为0
int result = 0;
//这条语句的理解建立在先理解下方for循环的基础之上。就是说每当有一组值凑够了目标数额,就意味着是一种成功的方法。
result = aim == 0 ? 1 : 0;
//for循环的循环出口为 index不能超过数组下标,当前面值数额不能超过目标数额,当前需要存在目标数额。
for(int i = 0; index < penny.length && penny[index]*i <= aim && aim > 0; i++){
//进行每一步的递归循环 每次循环的数额为减去已使用面值*数量的新产生的数额
result += res(penny,index+1,aim - penny[index]*i);
}
return result;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  编程 暴力求解