动态规划的一些练习题(上)

1. 零钱兑换

题目

class Solution {
   
    public int coinChange(int[] coins, int amount) {
   
        int n = coins.length;
        int[] arr = new int[amount + 1];// 0..amount

        // 定义初始条件
        arr[0] = 0;
        for(int i = 1; i <= amount; i++) {
   
            // 求arr[i]
            arr[i] = Integer.MAX_VALUE;
            for(int j = 0; j < n; j++) {
   
                if(i >= coins[j] && arr[i - coins[j]] != Integer.MAX_VALUE && arr[i - coins[j]] + 1 < arr[i]) {
   
                    arr[i] = arr[i - coins[j]] + 1;
                }

            }
        }
        if (arr[amount] == Integer.MAX_VALUE) {
   
            return -1;
        }else {
   
            return arr[amount];
        }
        

    }
}

2. 不同路径-1

题目

分析:

动态规划第一步:确定状态

a. 最后一步: 无论机器人最后是如何到达终点的,最后一步只有两种情况,那就是从左到右和从上到下。设目标位置为[m - 1][n -1],则是从[m-2][n-1]和[m - 1][n - 2]过来的。
b. 子问题,原问题是从[0][0]到[m-1][n-1]转化为有多少种方式从[0][0]走到[m-2][n-1]和有多少种方式从从[0][0]走到[m-1][n-2]

动态规划第二步:状态转移方程

f[i][j] = f[i - 1][j] + f[i][j - 1]

动态规划第三步:初始条件和边界条件

初始条件:f[0][0] = 1
边界条件:i = 0或者j = 0的时候,只能从一个方向过来f[0][j] =1 f[i][0] = 1

动态规划第四步:计算顺序

计算第0行
计算第1行
。。。
计算第m - 1行
答案就是f[m - 1][n -1]

class Solution {
   
    public int uniquePaths(int m, int n) {
   
        int[][] arr = new int[m][n];
        arr[0][0] = 1;
        for(int i = 0; i < m; i++) {
   
            for(int j = 0; j < n; j++) {
   
                if (i == 0 || j == 0) {
   
                    arr[i][j] = 1;
                }else{
   
                    arr[i][j] = arr[i][j - 1] + arr[i - 1][j];         
                }
                      
        }
    }
    return arr[m - 1][n - 1];
    }
}

3. 不同路径-2

题目

分析:这个题和1的区别在于 障碍的地方f[i][j] = 0,然后就是边界条件中在最上边和最左边不再是直接等于1了,而是由它前面一个来决定!

动态规划第一步:确定状态

a. 最后一步: 无论机器人最后是如何到达终点的,最后一步只有两种情况,那就是从左到右和从上到下。设目标位置为[m - 1][n -1],则是从[m-2][n-1]和[m - 1][n - 2]过来的。
b. 子问题,原问题是从[0][0]到[m-1][n-1]转化为有多少种方式从[0][0]走到[m-2][n-1]和有多少种方式从从[0][0]走到[m-1][n-2]

动态规划第二步:状态转移方程

f[i][j] = f[i - 1][j] + f[i][j - 1]

动态规划第三步:初始条件和边界条件

初始条件:f[0][0] = 1
边界条件:i = 0或者 j = 0, f[i][j] = f[i ][j - 1]或者f[i - 1][j]

动态规划第四步:计算顺序

class Solution {
   
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
   
        int m = obstacleGrid.length;
        int n = obstacleGrid[0].length;
        int[][] arr = new int[m][n];
        if(obstacleGrid[0][0] == 1 || obstacleGrid[m - 1][n - 1] == 1) {
   
            return 0;
        }else{
   
            arr[0][0] = 1;
            for(int i = 0; i < m; i++) {
   
                for(int j = 0; j < n; j++) {
   
                    if(obstacleGrid[i][j] == 1) {
   
                        arr[i][j] = 0;
                    }else{
   
                        if(i == 0 && j == 0){
   
                            arr[i][j] = 1;
                        }else{
   
                            if(i == 0) {
   
                                arr[i][j] = arr[i][j - 1];
                            }
                            if(j == 0) {
   
                                arr[i][j] = arr[i - 1][j];
                            }
                            if(i != 0 && j != 0) {
   
                                arr[i][j] = arr[i - 1][j]+ arr[i][j - 1];
                            }
                        }
                    }
                }
            }
        }

        return arr[m - 1][n - 1];
    }
}

4. 跳跃游戏

题目

分析:

动态规划第一步:确定状态

a. 最后一步: 无论怎么样到最后一步,都是前面的某一步直接跳过去的
b. 子问题,能成功跳到最后一步j位置是上一次跳成功了在i位置,并且i位置能跳的步数能够到j

动态规划第二步:状态转移方程

f[j] = or{i = 0到j-1}{f[i] && nums[i] > j - i}

动态规划第三步:初始条件和边界条件

初始条件:f[0]= true
边界条件:无

动态规划第四步:计算顺序

从小到大依次计算。

class Solution {
   
    public boolean canJump(int[] nums) {
   
        // f[j]是true的条件有两个
        // 1. f[i] = true 2. nums[i] > j - i
        if (nums == null || nums.length == 0) return false;
        int n = nums.length;
        boolean[] arr = new boolean[n+1];
        arr[0] = true;
        

        for(int i = 1; i < n; i++) {
   
            
            arr[i] = false; // 这儿是个小细节
            for(int j = 0; j < i; j++) {
   
                if(arr[j] && nums[j] >= i - j) {
   
                    arr[i] = true;
                    break;
                }
            }
           
        }
        return arr[n - 1];
    }
}

5. 粉刷房子

粉刷房子2请移步12题
题目
分析:
序列型动态规划:前i个最小/方式数/最小
序列➕状态

class Solution {
   
    public int minCost(int[][] costs) {
   
        int n = costs.length;// 房子的个数
        int[][] arr = new int[3][n];
        //arr[0][i] 代表第i栋房子是红色时,前i栋房子的最低价
        // arr[1][i] 代表第i栋房子是蓝色时,前i栋房子的最低价
        // arr[2][i] 代表第i栋房子是绿色时,前i栋房子的最低价

        // 初始条件
        for(int i = 0; i < 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值