换零钱--动态规划

题目示例:

【题目】
给定数组arr,arr中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim代表要找的钱数,求换钱有多少种方法。
【举例】
arr=[5,10,25,1],aim=0。
组成0元的方法有1种,就是所有面值的货币都不用。所以返回1。
arr=[5,10,25,1],aim=15。
组成15元的方法有6种,分别为3张5元,1张10元+1张5元,1张10元+5张1元,10张1元+1张5元,2张5元+5张1元,15张1元。所以返回6。
arr=[3,5],aim=2。
任何方法都无法组成2元。所以返回0。

解法一:暴力递归求解

/* 递归求解 */
int process1(vector<int> arr, int index, int aim)
{
    int res = 0;
    int i = 0;

    if (index == arr.size())
    {
        res = (aim == 0 ? 1:0);
    }
    else
    {
        for(i = 0; aim >= (arr[index]*i); i++)
        {
            res += process1(arr,index+1, aim - arr[index]*i);
        }
    }

    return res;
}

/* 暴力递归求解 */
int getCoinSorts1(vector<int> arr, int aim)
{
    if (arr.empty() || aim < 0)
    {
        return 0;
    }

    /* 求0到aim所有可能 */
    return process1(arr,0, aim);
}


解法二:动态规划 dp[i][j] = dp[i][j-arr[i]] + dp[i-1][j]

#include <iostream>
#include <vector>

using namespace std;

#define CHANGE_NUMBERS 4
#define MAX_AIM 1000


/* 暴力递归求解 */
int getCoinSorts2(vector<int> arr,const int aim)
{
    if (arr.empty() || aim < 0)
    {
        return 0;
    }

    int i = 0, j = 0;
    int result = 0;

    int dp[CHANGE_NUMBERS][MAX_AIM] = {0};
    /* 先求第一列的值 */
    for(i = 0; i < arr.size(); i++)
    {
        dp[i][0] = 1;
    }

    /* 再求第一行的值 */
    for(j = 1; arr[0]*j <= aim; j++)
    {
        dp[0][arr[0]*j] = 1;
    }

    /* 再求其他行和列的值 */
    for(i = 1; i < arr.size(); i++)
    {
        for(j = 1; j <= aim; j++)
        {
            dp[i][j] = dp[i-1][j];
            dp[i][j] += ((j - arr[i]) >= 0) ? dp[i][j-arr[i]] : 0;
        }
    }

    return dp[arr.size()-1][aim];
}

int main( void )
{
    int a[4] = {5,10,25,1};
    vector<int> arr(a,a+4) ;

    cout << getCoinSorts2(arr,15) << endl;


    return 0;
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dmfrm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值