我們正在玩乙個猜數遊戲,遊戲規則如下:
我從 1 到 n 之間選擇乙個數字,你來猜我選了哪個數字。
每次你猜錯了,我都會告訴你,我選的數字比你的大了或者小了。
然而,當你猜了數字 x 並且猜錯了的時候,你需要支付金額為 x 的現金。直到你猜到我選的數字,你才算贏得了這個遊戲。
示例:n = 10, 我選擇了8.
第一輪: 你猜我選擇的數字是5,我會告訴你,我的數字更大一些,然後你需要支付5塊。
第二輪: 你猜是7,我告訴你,我的數字更大一些,你支付7塊。
第三輪: 你猜是9,我告訴你,我的數字更小一些,你支付9塊。
遊戲結束。8 就是我選的數字。
你最終要支付 5 + 7 + 9 = 21 塊錢。
給定 n ≥ 1,計算你至少需要擁有多少現金才能確保你能贏得這個遊戲。
乍一眼看上去,很像二分的查詢方法,但是二分卻不能保證就一定是最小的那個方案。所以我們採用窮舉法(遞迴法)來分析。
首先,可以明確這個問題和區間是有關的,直接定義,狀態函式dp[
i][j
]dp[i][j]
dp[i][
j]區間[ i,
j]
[i,j]
[i,j
]之間消耗的確保獲勝最小現金。
要求得這個現金,我們需要按照最壞情況考慮,就是我們下一次猜測是錯誤的情況下,需要的資金,把所有猜測錯誤的情況列舉出來可以有
m ax
(dp[
i][k
−1],
dp[k
+1][
j])+
kk∈[
i+1,
j−1]
\begin max(dp[i][k-1], dp[k+1][j]) + k & & k\in[i+1,j-1] \end
max(dp
[i][
k−1]
,dp[
k+1]
[j])
+k
k∈[i
+1,j
−1]
這裡用max是因為給出提示後,只會選擇任一邊,為了保險起見,就選擇最大的部分。
在這些猜錯的最壞情況下,我們找到乙個最小現金,意味著我們在面對這個未知區間時,要盲猜乙個效率最高的數,這個數在列舉的k之中,這裡用min找到最小值。
d p[
i][j
]=
mink(
max(
dp[i
][k−
1],d
p[k+
1][j
])+k
)k∈[
i+1,
j−1]
\begin dp[i][j] =\min_k(max(dp[i][k-1], dp[k+1][j]) + k) & & k\in[i+1,j-1] \end
dp[i][
j]=k
min(m
ax(d
p[i]
[k−1
],dp
[k+1
][j]
)+k)
k∈
[i+1
,j−1
]到這裡我們已經把狀態轉移方程給弄出來。
首先我們可以確定dp[
i][i
]=0,
dp[0
][i]
=0,d
p[n]
[0]=
0dp[i][i]=0,dp[0][i]=0,dp[n][0]=0
dp[i][
i]=0
,dp[
0][i
]=0,
dp[n
][0]
=0,因為當相等的時候不需要猜,涉及0的時候在題目中不需要考慮。那麼剩下的值該如何進行設定?
觀察方程,最終列舉的時候取得是最小值,可以把dp[
i][j
]dp[i][j]
dp[i][
j]的初始值設定為正無窮。
首先可以確定,
i ≤k
−1
1≤ ji\leq k-1 < k+1\leq j i≤k− 11≤j這裡有個矛盾就是i,j之間的差是可以為1,而k+1與k-1的差為2,這點在迴圈的時候需要注意,即最後k的取值需要把邊界值i,j進行考慮。 其次,回顧轉移方程 d p[ i][j ]= mink( max( dp[i ][k− 1],d p[k+ 1][j ])+k )k∈[ i+1, j−1] \begin dp[i][j] =\min_k(max(dp[i][k-1], dp[k+1][j]) + k) & & k\in[i+1,j-1] \end dp[i][ j]=k min(m ax(d p[i] [k−1 ],dp [k+1 ][j] )+k) k∈ [i+1 ,j−1 ]當需要更新的dp[ i][j ]dp[i][j] dp[i][ j]時,需要用到左後方的dp,所以更新應該是從左到右,從下到上。class solution
for(int i=1;i<=n;i++)
}for(int i=0;i<=n;i++)
for(int i=0;i<=n;i++)
for(int i=0;i<=n;i++)
for(int j=2;j<=n;j++)
dp[i][j] = min(dp[i][j], i+dp[i+1][j]);
dp[i][j] = min(dp[i][j], j+dp[i][j-1]);}}
return dp[1][n];
}};```
LeetCode375 猜數字大小 II
我們正在玩乙個猜數遊戲,遊戲規則如下 我從1到n之間選擇乙個數字,你來猜我選了哪個數字。每次你猜錯了,我都會告訴你,我選的數字比你的大了或者小了。然而,當你猜了數字 x 並且猜錯了的時候,你需要支付金額為 x 的現金。直到你猜到我選的數字,你才算贏得了這個遊戲。示例 n 10,我選擇了8.第一輪 你...
LeetCode 375 猜數字大小II
我們正在玩乙個猜數遊戲,遊戲規則如下 我從 1 到 n 之間選擇乙個數字,你來猜我選了哪個數字。每次你猜錯了,我都會告訴你,我選的數字比你的大了或者小了。然而,當你猜了數字 x 並且猜錯了的時候,你需要支付金額為 x 的現金。直到你猜到我選的數字,你才算贏得了這個遊戲。示例 n 10,我選擇了8.第...
375 猜數字大小 II
我們正在玩乙個猜數遊戲,遊戲規則如下 我從1到n之間選擇乙個數字,你來猜我選了哪個數字。每次你猜錯了,我都會告訴你,我選的數字比你的大了或者小了。然而,當你猜了數字 x 並且猜錯了的時候,你需要支付金額為 x 的現金。直到你猜到我選的數字,你才算贏得了這個遊戲。示例 n 10,我選擇了8.第一輪 你...