算法设计大赛T11

我们正在玩一个猜数游戏,游戏规则如下:
我从 1 到 n 之间选择一个数字,你来猜我选了哪个数字。
每次你猜错了,我都会告诉你,我选的数字比你的大了或者小了。
然而,当你猜了数字 x 并且猜错了的时候,你需要支付金额为 x 的现金。直到你猜到我选的数字,你才算赢得了这个游戏。
给定 n ≥ 1,计算你至少需要拥有多少现金才能确保你能赢得这个游戏。

做了好多的简单题,终于进军到中等题了,那么我们先看看第12题,也就是力扣375题,猜数字大小Ⅱ怎么做吧!

思路:
看到这题可能会有很多同学的第一想法便是猜数字大小Ⅰ中的二分法,但实际上二分法求出的最终结果并不是我们要找的最优解,因为我们每次猜错数字,都需要支付为猜错数字大小的cost,故结果与猜的次数以及猜的数字都有关系。
题目中,我们需要求得至少需要拥有多少现金才能稳赢,所以我们在必定猜中的那一次之前,所有的猜测都是错误的,即求最小的最大损失。听起来可能有些绕口,看下代码中的转化公式可能会更加明了一些。
这题的基本思路采用动态规划,求从1到n的cost,假定我们先选择1到n间的某个数x作为第一次猜测的结果,那最终结果
res = max(cost(1:x-1) + cost(x+1:n)) + x
根据这个公式,我们要求cost(1:n),需对1到n中的数字依次带入公式求解,我们设dp[1][n]为我们需求的结果,采用自底向上的策略,所需dp的空间为右上方的三角矩阵,由dp[n][n]开始依次求解,代码如下:

class Solution:
    def getMoneyAmount(self, n: int) -> int:
        dp = [[0 for _ in range(n+1)] for _ in range(n+1)]
        for i in range(n,0,-1):
            for j in range(i+1,n+1):
                dp[i][j] = min(x + max(dp[i][x-1],dp[x+1][j]) for x in range(i,j))
        return dp[1][-1]

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值