动态规划练习——从暴力递归—>记忆化搜索—>经典动态规划

简介: 动态规划练习——从暴力递归—>记忆化搜索—>经典动态规划

题目

给定一个数组arr,全是正数且没有重复值,数组元素是人民币面值大小,可以重复取值。常量aim==1000元,要求从数组中取元素使得面值加起来为1000,求有多少种方式?

package com.harrison.class13;

public class Code06_CoinsWay {
    public static int ways1(int[] arr,int aim) {
        if(arr==null || arr.length==0 || aim<0) {
            return 0;
        }
        return process1(arr, 0, aim);
    }
    
    // arr[index...]所有的面值都可以自由使用任意张
    // 组成rest有多少种方法
    public static int process1(int[] arr,int index,int rest) {
//        if(rest<0) {
//            return 0;
//        }
        // rest>=0
        if(index==arr.length) {// 当前位置来到了最后一张货币,没有货币可以选择了
            return rest==0?1:0;
        }
        // 当前有货币 arr[index]
        int ways=0;
        for(int zhang=0; zhang*arr[index]<=rest; zhang++) {
            ways+=process1(arr, index+1, rest-(zhang*arr[index]));
        }
        return ways;
    }
    
    public static int ways2(int[] arr,int aim) {
        if(arr==null || arr.length==0 || aim<0) {
            return 0;
        }
        int[][] dp=new int[arr.length+1][aim+1];
        // 一开始所有的过程都没有计算 dp[..][..]=-1
        for(int i=0; i<dp.length; i++) {
            for(int j=0; j<dp[0].length; j++) {
                dp[i][j]=-1;
            }
        }
        return process2(arr, 0, aim,dp);
    }
    
    // 如果index和rest的参数组合是没有算过的,dp[index][rest] == -1
    // 如果index和rest的参数组合是算过的,dp[index][rest] > -1
    public static int process2(int[] arr,int index,int rest,int[][] dp) {
        if(dp[index][rest]!=-1) {
            return dp[index][rest];
        }
        if(index==arr.length) {
            dp[index][rest]=rest==0?1:0;
            return dp[index][rest];
        }
        int ways=0;
        for(int zhang=0; zhang*arr[index]<=rest; zhang++) {
            ways+=process2(arr, index+1, rest-(zhang*arr[index]),dp);
        }
        dp[index][rest]=ways;
        return ways;
    }
    
    public static int ways3(int[] arr,int aim) {
        if(arr==null || arr.length==0 || aim<0) {
            return 0;
        }
        int N=arr.length;
        int[][] dp=new int[N+1][aim+1];
        dp[N][0]=1;// dp[N]][1...aim]=0;
        // 第N行已经填好了,从第N-1行开始填
        for(int index=N-1; index>=0; index--) {
            for(int rest=0; rest<=aim; rest++) {
                int ways=0;
                for(int zhang=0; zhang*arr[index]<=rest; zhang++) {
                    ways+=dp[index+1][rest-(zhang*arr[index])];
                }
                dp[index][rest]=ways;
            }
        }
        return dp[0][aim];
    }
    
    public static int ways4(int[] arr,int aim) {
        if(arr==null || arr.length==0 || aim<0) {
            return 0;
        }
        int N=arr.length;
        int[][] dp=new int[N+1][aim+1];
        dp[N][0]=1;
        for(int index=N-1; index>=0; index--) {
            for(int rest=0; rest<=aim; rest++) {
                dp[index][rest]=dp[index+1][rest];
                if(rest-arr[index]>=0) {
                    dp[index][rest]+=dp[index][rest-arr[index]];
                }
            }
        }
        return dp[0][aim];
    }
    
    public static void main(String[] args) {
        int[] arr= {5,10,50,100};
        int sum=1000;
        System.out.println(ways1(arr, sum));
        System.out.println(ways2(arr, sum));
        System.out.println(ways3(arr, sum));
        System.out.println(ways4(arr, sum));
    }
}
相关文章
|
1月前
|
算法 Python
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果;贪心算法在每一步选择局部最优解,追求全局最优;动态规划通过保存子问题的解,避免重复计算,确保全局最优。这三种算法各具特色,适用于不同类型的问题,合理选择能显著提升编程效率。
51 2
|
存储 人工智能 分布式计算
动态规划从理论到实践-深入理解贪心/分治/回溯/动态规划的算法思想
动态规划从理论到实践-深入理解贪心/分治/回溯/动态规划的算法思想
254 0
|
算法
解密汉诺塔问题:递归与分治的经典探索
解密汉诺塔问题:递归与分治的经典探索
599 0
|
搜索推荐 容器
暴力递归:动态规划的雏形
暴力递归:动态规划的雏形
|
机器学习/深度学习 缓存 机器人
从暴力递归到动态规划,记忆化搜索
从暴力递归到动态规划,记忆化搜索
从暴力递归到动态规划,记忆化搜索
|
存储 缓存 算法
面试官问我斐波拉契数列,我从暴力递归讲到动态规划 ...
面试官问我斐波拉契数列,我从暴力递归讲到动态规划 ...
递归与动态规划
凡是递归的过程,都可以化成树的过程。递归就是问题变成子问题求解的过程。动态规划暂时没明白,好像是需要一张动态规划表,是根据递归搞出来的。 问题1:开始有一头母牛,母牛每年会生一只母牛,新出生的母牛成长三年后也能每年生一只母牛,假设牛都不会死。
697 0
|
C++ 缓存
careercup-递归和动态规划 9.11
9.11 给定一个布尔表达式,由0、1、&、|和^等符号组成,以及一个想要的布尔结果result,实现一个函数,算出有几种括号的放法可使该表达式得出result值。 解法: 跟其他递归问题一样,此题的关键在于找出问题与子问题之间的关系。
717 0