换钱的方法数

换钱的方法数

http://www.nowcoder.com/questionTerminal/39cb6c6e2b844a8cba382c8e26951e0a

话不多说上代码。解释书上有。
import java.util.Scanner;

public class Main{
public static final int mod = 1_000_000_007;

public static int coins1(int[] arr, int aim){
    if(arr.length == 0 || arr == null || aim < 0){
        return 0;
    }
    int[][] map = new int[arr.length+1][aim+1];
    return process1(arr, 0, aim, map);  
}
//暴力递归的方法
public static int process(int[] arr, int index, int aim){
    int res = 0;
    //base case
    if(index == arr.length){
          res = aim == 0 ? 1 : 0;
    }else{
             for(int k = 0; k * arr[index] <= aim; k ++){
                res += process(arr, index+1, aim - k * arr[index]);
              }
          }
    return res;
}
//记忆搜索的方法
public static int process1(int[] arr, int index, int aim, int[][] map){
    int res = 0;
    //base case
    if(index == arr.length){
          res = aim == 0 ? 1 : 0;
    }else{   
             int mapValue = 0;
             for(int k = 0; k * arr[index] <= aim; k ++){
                 mapValue = map[index+1][aim - k * arr[index]];
                 if(mapValue != 0){
                     res += mapValue == -1 ? 0 : mapValue;
                 }else{
                     res += process(arr, index+1, aim - k * arr[index]);
                 }
              }
          }
    map[index][aim] = res == 0 ? -1 : res; 
    return res;
}
//暴力递归——动态规划
public static int coins3(int[] arr, int aim){
    if(arr.length == 0 || arr == null || aim < 0){
        return 0;
    }
    //dp[i][j]:钱arr[0...i],目标j 有多少做法
    int[][] dp = new int[arr.length][aim+1];
    //base case
    for(int i = 0; i < arr.length; i++){
        dp[i][0] = 1;
    }
    for(int j = 1; arr[0] * j <= aim; j++){
        dp[0][arr[0] * j] = 1;
    }
    int num = 0;
    //遍历dp数组
    for(int i = 1; i < arr.length; i++){
        for(int j = 1; j <= aim; j ++){
            num = 0;
            //如何求dp[i][j]?
            for(int k = 0; j - k*arr[i] >= 0 ; k++){
                num = (num + dp[i-1][j - k*arr[i]]) % mod;
            }
            dp[i][j] = num;        
        }
    }
    return dp[arr.length-1][aim];
}
//动态规划O(N aim)
public static int coins4(int[] arr, int aim){
    if(arr.length == 0 || arr == null || aim < 0){
        return 0;
    }
    //dp[i][j]:钱arr[0...i],目标j 有多少做法
    int[][] dp = new int[arr.length][aim+1];
    //base case
    for(int i = 0; i < arr.length; i++){
        dp[i][0] = 1;
    }
    for(int j = 1; arr[0] * j <= aim; j++){
        dp[0][arr[0] * j] = 1;
    }
    //遍历dp数组
    for(int i = 1; i < arr.length; i++){
        for(int j = 1; j <= aim; j ++){
            dp[i][j] = dp[i-1][j] % mod;
            dp[i][j] = (dp[i][j] +  (j - arr[i] >= 0 ? dp[i][j-arr[i]] : 0) )% mod;
        }
    }
    return dp[arr.length-1][aim];
}
//本题的最优解 时间O(N aim) 空间O(aim)
 public static int coins5(int[] arr, int aim){
    if(arr.length == 0 || arr == null || aim < 0){
        return 0;
    }
    //dp[i][j]:钱arr[0...i],目标j 有多少做法
    int[] dp = new int[aim+1];
    //dp[0] = 1;
    for(int j = 0; arr[0] * j <= aim; j++){
        dp[arr[0] * j] = 1;
    }
    //遍历dp数组
    for(int i = 1; i < arr.length; i++){
        for(int j = 1; j <= aim; j ++){
            dp[j] = dp[j] % mod;
            dp[j] = (dp[j] +  (j - arr[i] >= 0 ? dp[j-arr[i]] : 0) )% mod;
        }
    }
    return dp[aim];
}   
public static void main(String[] args){
    Scanner sc = new Scanner(System.in);
    int n = sc.nextInt();
    int aim = sc.nextInt();
    int[] arr = new int[n];
    for(int i = 0; i < n; i++){
        arr[i] = sc.nextInt();
    }
    System.out.println(coins5(arr, aim));
}

}

全部评论

相关推荐

jack_miller:杜:你不用我那你就用我的美赞臣
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务