换钱方法数

题目描述

给定数组arr,设数组长度为n,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim,代表要找的钱数,求换钱的方法数有多少种。由于方法的种数比较大,所以要求输出对10^9+7109+7进行取模后的答案。

输入描述:

输出包括两行,第一行包括两个整数n(0≤n≤1000)和aim(0≤aim≤20000)。第二行包含n个整数,表示arr数组(1≤arr[i]​≤1e9)。

输出描述:

输出一个整数,表示换钱的方法数。
#include<iostream>
#include<vector>

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

}

int coins1(vector<int> arr, int aim){
    //暴力递归
    if(arr.empty() || aim<=0){
        return 0;
    }
    return process1(arr, 0, aim);

}
int process2(vector<int> &arr, int index, int aim, vector<vector<int>> &m){
    int res=0;
    if(index == arr.size()){
        res = aim ==0 ? 1:0;
    }else{
        int mapValue = 0;
        for(int i=0;arr[index]*i<=aim;i++){
            mapValue = m[index+1][aim-arr[index]*i];
            if(mapValue!=0){
                res += mapValue == -1?0:mapValue;
            }else{
                res += process2(arr, index+1, aim-arr[index]*i, m);
            }

        }
    }
    m[index][aim] = res == 0?-1:res;//m[i][j]=-1表示递归过程p(i,j)计算过,但是返回值为0
    return res;
}
int coins2(vector<int> &arr, int aim){
    //记忆化搜索
    if(arr.empty() || aim<=0){
        return 0;
    }
    vector<vector<int>> map(arr.size()+1, vector<int> (aim+1, 0));
    return process2(arr, 0, aim, map);
}
int coins3(vector<int> arr, int aim){
    //动态规划
    int n = arr.size();
    vector<vector<int>> dp(n,vector<int>(aim+1));
    for(int row = 0;row < n; row++){
        dp[row][0] = 1;
    }
    for(int j = 1; arr[0]*j <= aim;j++){
        dp[0][arr[0]*j]=1;
    }
    int num = 0;
    for(int i=1;i<n;i++){
        for(int j = 1;j<=aim; j++){
            num = 0;
            for(int k = 0;j-arr[i]*k >= 0; k++){
                num += dp[i-1][j-arr[i]*k];
            }
            dp[i][j]=num;
        }
    }
    return dp[n-1][aim];
}

int coins4(vector<int> arr, int aim){
    //O(N X aim)时间复杂度的动态规划
    if(arr.empty()||aim<0) return 0;
    int n = arr.size();
    vector<vector<int>> dp(n,vector<int>(aim+1));
    for(int row = 0;row < n; row++){
        dp[row][0] = 1;
    }
    for(int j = 1; arr[0]*j <= aim;j++){
        dp[0][arr[0]*j]=1;
    }
    int num = 0;
    for(int i=1;i<n;i++){
        for(int 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[n-1][aim];
}
int coins5(vector<int> arr, int aim){
    //O(N X aim)时间复杂度,O(aim)空间复杂度的动态规划
    if(arr.empty()||aim<0) {
        return 0;
    }
    int n = arr.size();
    vector<int> dp(aim+1, 0);
    dp[0]=1;
    for(int j = 1; arr[0]*j <= aim;j++){
        dp[arr[0]*j]=1;
    }
    for(int i=1;i<n;i++){
        for(int j = 1;j<=aim; j++){
            dp[j] += j-arr[i] >= 0 ? dp[j-arr[i]] : 0;
        }
    }
    return dp[aim];
}
int main(){
    /*
    int n, aim;
    cin>>n>>aim;
    vector<int> arr(n, 0);
    cout<<coins1(arr, aim)<<endl;
    */
    vector<int> arr={2, 3, 5, 7, 10};
    cout<<coins5(arr, 1000)<<endl;
    system("pause");
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值