leetcode375. 猜数字大小 II (区间dp)

题目

在这里插入图片描述

在这里插入图片描述

思路:
-----分析:

  1. 猜数字的过程中需满足确保获胜且最小现金
  2. 无论猜那个数都得满足1. 中的条件,于是不能使用二分,我们必须对所有情况进行决策
  3. 确定最优子结构:当只有两个数时,选取两个数都可确保获胜,但选小的那个,能满足最小现金
  4. 将最优子结构状态转移至全局,在1~n中选取一个数,两边都得是最优子结构,再在子结构中选取最优解
  5. 确定状态转移方程dp[i][j]=Math.min(dp[i][j],k+Math.max(dp[i][k-1],dp[k+1][j]));

-----注意:

  1. 通过递推方程,我们知道dp[i][j]是由子区间确定的,我们必须得确定子区间的值,例如我们若想要知道dp[1][3] 我们 必须得知道dp(1,2),dp(2,3), 当然,你可以先求dp(1,2),再求dp(2,3)也可先求dp(2,3)和dp(1,2)
  2. 下面给出两种(从后往前,从前往后)求出子结构,最后求出整个结构的最优的方式

代码:

class Solution {
    public int getMoneyAmount(int n) {
        // dp[i][j]  表示从i,j中取出确保获胜的最小现金数
        int[][] dp=new int[n+1][n+1];
        //由于当前问题可以拆分成若干个子问题(猜了一个数,再从剩余数中获取确保获胜且最小)
        // 最后模拟出dp[1][n]

        // 方式一
        // for(int i=n-1;i>=1;i--){
        //     for(int j=i+1;j<=n;j++){
        //         //枚举出所有子区间
        //         dp[i][j]=Integer.MAX_VALUE;
        //         for(int k=i;k<j;k++){
        //             //每个区间都选一个数
        //             dp[i][j]=Math.min(dp[i][j],k+Math.max(dp[i][k-1],dp[k+1][j]));
        //         }
        //     }
        // }


        //方式二
        for(int j=1;j<=n;j++){
            for(int i=j-1;i>=1;i--){
                dp[i][j]=Integer.MAX_VALUE;
                for(int k=i;k<j;k++){
                    dp[i][j]=Math.min(dp[i][j],k+Math.max(dp[i][k-1],dp[k+1][j]));
                }
            }
        }

        return dp[1][n];
    }

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值