关于动态规划的练习题

动态规划练习题

1.给出不同面额的硬币以及一个总金额. 写一个方法来计算给出的总金额可以换取的最少的硬币数量. 如果已有硬币的任意组合均无法与总金额面额相等, 那么返回 -1。

    public static int dp(int[] arr, int count) {
        int[] cost = new int[count + 1];
        int n = arr.length;
        //初始条件为0,即0块钱需要0枚硬币
        cost[0] = 0;
        for (int i = 1; i <= count; i++) {
            //先将cost的值设为无穷大,意为该额度无法凑硬币
            cost[i] = Integer.MAX_VALUE;
            //遍历硬币的额度
            for (int j = 0; j < n; j++) {
                //将问题化为子问题
                //如果下标不为负数并且该额度可以凑硬币则执行语句
                if (i - arr[j] >= 0 && cost[i - arr[j]] != Integer.MAX_VALUE) {
                    //设最后一枚硬币为cost[i],即最少枚数为cost[i-arr[j]]加上最后一枚硬币或者不加最后一枚硬币
                    cost[i] = Math.min(cost[i], cost[i - arr[j]] + 1);
                }
            }
        }
        //如果不能凑成额度,则返回-1
        if (cost[count] == Integer.MAX_VALUE) {
            return -1;
        }
        return cost[count];
    }

2.有一个机器人的位于一个 m × n 个网格左上角。机器人每一时刻只能向下或者向右移动一步。机器人试图达到网格的右下角。问有多少条不同的路径?

    public static int dp(int m,int n) {
        int[][] num = new int[m][n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                //如果在第一行或者第一列,意味着只能向下或向右走
                //所以只有一种方法
                if (i == 0 || j == 0) {
                    num[i][j] = 1;
                } else {
                    //走向最后一列的方法有最后一步是向下走
                    //或者最后一步向右走
                    //这两种方法加起来即为走到最后一点的方式
                    num[i][j] = num[i - 1][j] + num[i][j - 1];
                }
            }
        }
        return num[m - 1][n - 1];
    }

3.在一个数组arr中,找出一组不相邻的数字,使得最后的和最大。

    public static int dp(int[] arr) {
        //定义存储最大和的数组
        int[] opt = new int[arr.length];
        //如果只有一个元素,则该元素就是最大和
        opt[0] = arr[0];
        //如果只有两个元素,比较两个元素大小
        opt[1] = Math.max(arr[0], arr[1]);
        for (int i = 2; i < arr.length; i++) {
            //此时又分为选当前的数和不选两种情况
            //如果选当前的数,则相邻的无法选择
            //否则就看前一个数的最优解
            opt[i] = Math.max(opt[i - 1], opt[i - 2] + arr[i]);
        }
        return opt[arr.length - 1];
    }

4.给定一个正整数s, 判断一个数组arr中,是否有一组数字加起来等于s。

    public static boolean dp(int[] arr, int n) {
        boolean[][] dpArray = new boolean[arr.length][n + 1];
        for (int i = 0; i < arr.length; i++) {
            //当n为0时,代表已经有数拼凑成,所以第一列全部为true
            dpArray[i][0] = true;
        }
        //当下标为0时,除非arr[0]==n,否则全部为false
        Arrays.fill(dpArray[0], false);
        if (n >= arr[0]) {
            //如果n的值大于等于arr[0],则置为true
            dpArray[0][arr[0]] = true;
        }
        for (int i = 1; i < arr.length; i++) {
            for (int j = 1; j < n + 1; j++) {
                if (arr[i] > j) {
                    //如果arr[i]的值大于j,则说明不能选该值,此时只有一种情况
                    dpArray[i][j] = dpArray[i - 1][j];
                } else {
                    //否则就看两种情况之一是否满足
                    dpArray[i][j] = dpArray[i - 1][j - arr[i]] || dpArray[i - 1][j];
                }
            }
        }
        return dpArray[arr.length - 1][n];
    }
发布了24 篇原创文章 · 获赞 32 · 访问量 1698

猜你喜欢

转载自blog.csdn.net/weixin_45729946/article/details/103550939