换钱的方法数

https://www.nowcoder.com/practice/39cb6c6e2b844a8cba382c8e26951e0atpId=101&tqId=33087&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking

题目描述

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

输入描述:

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

输出描述:

输出一个整数,表示换钱的方法数对10^9+7取模后的答案。

示例1

输入

4 15 5 10 25 1

输出

6

示例2

输入

5 1000
2 3 5 7 10

输出

20932712

备注:

时间复杂度O(N∗aim),空间复杂度O(aim)。
//方法1:暴力枚举
//运行超时:您的程序未能在规定时间内运行结束,请检查是否循环有错或算法复杂度过大。
//case通过率为0.00%   示例1可通过,vs2017
#include<bits/stdc++.h>
using namespace std;
const int number=1000000007;
int process(vector<int>& arr,int i,int rest){
    if(i==arr.size()){
        return (rest==0 ? 1 : 0);
    }
    int res=0;
    for(int k=0;k*arr[i]<=rest;k++){
        res+=process(arr,i+1,rest-k*arr[i]);
        res%=number;
    }
    return res;
}
int main(){
    int n,aim;
    cin>>n>>aim;
    vector<int> arr(n);
    for(int i=0;i<n;i++){
        cin>>arr[i];
    }
    cout<<process(arr,0,aim)<<endl;
    return 0;
}
//方法2:记忆化搜索 ac
//O(n*aim^2)  O(n*aim)
#include<bits/stdc++.h>
using namespace std;
const int number=1000000007;
vector<vector<int>> memo;
int process(vector<int>& arr,int i,int rest){
    if(i==arr.size()){
        return (rest==0 ? 1 : 0);
    }
    if(memo[i][rest]!=-1){
        return memo[i][rest];
    }
    int res=0;
    for(int k=0;k*arr[i]<=rest;k++){
        res+=process(arr,i+1,rest-k*arr[i]);
        res%=number;
    }
    memo[i][rest]=res;
    return res;
}
int main(){
    int n,aim;
    cin>>n>>aim;
    vector<int> arr(n);
    for(int i=0;i<n;i++){
        cin>>arr[i];
    }
    memo=vector<vector<int>>(n,vector<int>(aim+1,-1));
    cout<<process(arr,0,aim)<<endl;
    return 0;
}
//方法3:动态规划  O(n*aim)  O(n*aim)
//dp[i][j]的定义是在使用arr[0..i]货币的情况下,组成钱数j有多少种方法
#include<bits/stdc++.h>
using namespace std;
const int number=1000000007;
int main(){
    int n,aim;
    cin>>n>>aim;
    vector<int> arr(n);
    for(int i=0;i<n;i++){
        cin>>arr[i];
    }
    vector<vector<int>> dp(n,vector<int>(aim+1,0));  
    for(int i=0;i<n;i++){
        dp[i][0]=1;   //对于钱数为0,有1种方法
    }
    for(int j=1;j*arr[0]<=aim;j++){ //使用钱币arr[0]可以找开的钱数,都有这一种方法
        dp[0][j*arr[0]]=1;
    }
    for(int i=1;i<n;i++){
        for(int j=1;j<=aim;j++){
            dp[i][j]=dp[i-1][j];    //不使用arr[i]有多少种找法
            if(j-arr[i]>=0){
                dp[i][j]=(dp[i][j]+dp[i][j-arr[i]])%number; //加上使用arr[i]的找法
            }
        }
    }
    cout<<dp[n-1][aim]<<endl;
    return 0;
}
//方法4:优化方法3的空间
//O(n*aim)  O(aim)
#include<bits/stdc++.h>
using namespace std;
const int number=1000000007;
int main(){
    int n,aim;
    cin>>n>>aim;
    vector<int> arr(n);
    for(int i=0;i<n;i++){
        cin>>arr[i];
    }
    vector<int> dp(aim+1,0);  
    dp[0]=1;    //对于钱数为0,有1种方法      
    for(int i=0;i<n;i++){
        for(int j=arr[i];j<=aim;j++){
            dp[j]=(dp[j]+dp[j-arr[i]])%number;
        }
    }
    cout<<dp[aim]<<endl;
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值