标签:tps 举例 wrong alt 例子 没有 info from problems
We are playing the Guess Game. The game is as follows:
I pick a number from 1 to n. You have to guess which number I picked.
Every time you guess wrong, I‘ll tell you whether the number I picked is higher or lower.
However, when you guess a particular number x, and you guess wrong, you pay $x. You win the game when you guess the number I picked.
n = 10, I pick 8.
First round: You guess 5, I tell you that it‘s higher. You pay $5.
Second round: You guess 7, I tell you that it‘s higher. You pay $7.
Third round: You guess 9, I tell you that it‘s lower. You pay $9.
Game over. 8 is the number I picked.
You end up paying $5 + $7 + $9 = $21.
Given a particular n ≥ 1, find out how much money you need to have to guarantee a win.
我们正在玩一个猜数游戏,游戏规则如下:
我从 1 到 n 之间选择一个数字,你来猜我选了哪个数字。
每次你猜错了,我都会告诉你,我选的数字比你的大了或者小了。
然而,当你猜了数字 x 并且猜错了的时候,你需要支付金额为 x 的现金。直到你猜到我选的数字,你才算赢得了这个游戏。
n = 10, 我选择了8.
第一轮: 你猜我选择的数字是5,我会告诉你,我的数字更大一些,然后你需要支付5块。
第二轮: 你猜是7,我告诉你,我的数字更大一些,你支付7块。
第三轮: 你猜是9,我告诉你,我的数字更小一些,你支付9块。
游戏结束。8 就是我选的数字。
你最终要支付 5 + 7 + 9 = 21 块钱。
给定一个 n ≥ 1,计算你至少需要拥有多少现金才能确保你能赢得这个游戏。
??刚开始看到这个题,感觉是个数学问题,可以直接计算得出。写了很久都不AC,于是又老实写算法了。从算法角度看,这个题就是很直白的暴力破解,中间用到了DP来减小运算复杂度,还包含了取最大值和最小值运算,所以不太好分类,但是思想还是能理明白。最重要的一步DP就是i+max(?[1,...,i-1]?,?[i+1,...,n]?)。这里的[1,...,i-1]表示猜对这个短序列最少花的钱。
??下面举例说明。
当序列很短的时候,一眼就能看出来最少花多少钱。比如长度为2的短序列:
1 | 2 |
---|
显然猜1可以花钱最少,猜对不花钱,错了花1块,所以最多需要1块钱。
长度为3的短序列同理。比如:
2 | 3 | 4 |
---|
对于中长序列,比如1到4的序列怎么处理呢,其实逻辑一样:
1 | 2 | 3 | 4 |
---|
先猜1
1 | 2 | 3 | 4 |
---|
先猜2
1 | 2 | 3 | 4 |
---|
先猜3
1 | 2 | 3 | 4 |
---|
先猜4
1 | 2 | 3 | 4 |
---|
再举一个长序列的例子说明任务分解,比如1到10:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|
for i in range(1,11)
从头试到尾,这样把任务分成了两个小任务,即[1,...,i-1]和[i+1,...,10],然后只要我们知道每个小任务的解,那么先猜i的这个大任务的解就是i+max([1,...,i-1],[i+1,...,10])。
比如我们先猜了6
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|
最后的问题是怎么构造二维数组存储小任务的解呢,也很简单。这里以1到6举例,太长表格不好画。
1 | 2 | 3 | 4 | 5 | 6 |
---|
表格建立如下,记为T:
1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|
1 | ||||||
2 | ||||||
3 | ||||||
4 | ||||||
5 | ||||||
6 |
首先初始化表格为0
1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|
1 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | 0 | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | 0 | 0 | 0 | 0 |
6 | 0 | 0 | 0 | 0 | 0 | 0 |
任务终点为1的时候,此时序列为[ 1 ],不用花钱就能猜对,则有T[1][1]=0。
终点为1填写完毕。此时T没变
1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|
1 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | 0 | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | 0 | 0 | 0 | 0 |
6 | 0 | 0 | 0 | 0 | 0 | 0 |
任务终点为2的时候,
任务起点先设为2,此时序列为[ 2 ],不用花钱,则有T[2][2]=0。
下一步任务起点设为1,此时序列为[ 1 , 2 ],花1即可,则有T[2][1]=1。
终点为2填写完毕,此时T为
1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|
1 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 1 | 0 | 0 | 0 | 0 | 0 |
3 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | 0 | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | 0 | 0 | 0 | 0 |
6 | 0 | 0 | 0 | 0 | 0 | 0 |
任务终点为3的时候,
任务起点先设为3,此时序列为[ 3 ],不用花钱,则有T[3][3]=0。
任务起点设为2,此时序列为[ 2 , 3 ],花钱2,则有T[3][2]=2。
任务起点设为1,此时序列为[ 1 , 2 ,3 ],三个的短序列直接可得花钱为中间那个数,也就是2,则有T[3][1]=2。
终点为3填写完毕,此时T为
1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|
1 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 1 | 0 | 0 | 0 | 0 | 0 |
3 | 2 | 2 | 0 | 0 | 0 | 0 |
4 | 0 | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | 0 | 0 | 0 | 0 |
6 | 0 | 0 | 0 | 0 | 0 | 0 |
任务终点为4的时候,
任务起点设为4,此时序列为[ 4 ],不花钱,T[4][4]=0。
任务起点设为3,此时序列为[ 3 , 4 ],花钱3,则有T[4][3]=3。
任务起点设为2,此时序列为[ 2 , 3 , 4 ],花钱3,则有T[4][2]=3。
任务起点设为1,此时序列为[ 1 , 2 , 3 , 4 ],长度超过3了,要用中长序列的方式去计算。也就是前面举例的方式,有T[4][1]=min(先猜1花的钱,...,先猜4花的钱)
\[
\begin{array}{l}
=min(1+[2,3,4] \ , \ 2+max([1],[3,4]) \ , \ 3+max([1,2],[4] \ , \ 4+[1,2,3])) \=min(1+T[4][2] \ , \ 2+max(T[1][1],T[4][3]) \ , \ 3+max(T[2][1],T[4][4]) \ , \ 4+T[3][1]) \=min(1+3 \ , \ 2+3 \ , \ 3+1 \ , \ 4+2) \=4
\end{array}
\]
即T[4][1]=4。
终点为4填写完毕,此时T为
1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|
1 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 1 | 0 | 0 | 0 | 0 | 0 |
3 | 2 | 2 | 0 | 0 | 0 | 0 |
4 | 4 | 3 | 3 | 0 | 0 | 0 |
5 | 0 | 0 | 0 | 0 | 0 | 0 |
6 | 0 | 0 | 0 | 0 | 0 | 0 |
终点为5填写完毕,此时T为
1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|
1 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 1 | 0 | 0 | 0 | 0 | 0 |
3 | 2 | 2 | 0 | 0 | 0 | 0 |
4 | 4 | 3 | 3 | 0 | 0 | 0 |
5 | 6 | 6 | 4 | 4 | 0 | 0 |
6 | 0 | 0 | 0 | 0 | 0 | 0 |
任务终点为6的时候,
任务起点设为6,此时序列为[ 6 ],不花钱,T[6][6]=0。
任务起点设为5,此时序列为[ 5 , 6 ],花钱5,则有T[6][5]=5。
任务起点设为4,此时序列为[ 4 , 5 , 6 ],花钱5,则有T[6][4]=5。
任务起点设为3,此时序列为[ 3 , 4 , 5 , 6 ],有
\[
\begin{array}{l}
T[6][3] \=min(3+T[6][4],4+max(T[3][3],T[6][5]),5+max(T[4][3],T[6][6]),6+T[5][3]) \=min(3+5,4+5,5+3,6+4) \=8
\end{array}
\]
任务起点设为2,此时序列为[ 2 , 3 , 4 , 5 , 6 ],有
\[
\begin{array}{l}
T[6][2] \=min(2+T[6][3],3+max(T[2][2],T[6][4]),4+max(T[3][2],T[6][5]),5+max(T[4][2],T[6][6]),6+T[5][2]) \=min(2+8,3+5,4+5,5+3,6+6) \=8
\end{array}
\]
任务起点设为1,此时序列为[ 1 , 2 , 3 , 4 , 5 , 6 ],有
\[
\begin{array}{l}
T[6][1] \=min(1+T[6][2],2+max(T[1][1],T[6][3]),3+max(T[2][1],T[6][4]),4+max(T[3][1],T[6][5]),5+max(T[4][1],T[6][6]),6+T[5][1]) \=min(1+8,2+8,3+5,4+5,5+4,6+6) \=8
\end{array}
\]
终点为6填写完毕,此时整个表格填写完毕。
有T为
1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|
1 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 1 | 0 | 0 | 0 | 0 | 0 |
3 | 2 | 2 | 0 | 0 | 0 | 0 |
4 | 4 | 3 | 3 | 0 | 0 | 0 |
5 | 6 | 6 | 4 | 4 | 0 | 0 |
6 | 8 | 8 | 8 | 5 | 5 | 0 |
到此,T[6][1]=8即为结果。再把上述思路转为代码就搞定了。
class Solution:
def getMoneyAmount(self, n):
"""
:type n: int
:rtype: int
"""
L = [[0]*(n+1) for i in range(n+1)]
for i in range(1,n+1):
for j in range(1,i)[::-1]:
M = n*n
if i-j<=2:
M = i-1
else:
for k in range(j+1,i):
M = min(M,k+max(L[k-1][j],L[i][k+1]))
L[i][j] = M
return L[n][1]
375. Guess Number Higher or Lower II (Python)
标签:tps 举例 wrong alt 例子 没有 info from problems
原文地址:https://www.cnblogs.com/initial-h/p/9536480.html