我們正在玩乙個猜數遊戲,遊戲規則如下:
我從 1 到 n 之間選擇乙個數字,你來猜我選了哪個數字。
每次你猜錯了,我都會告訴你,我選的數字比你的大了或者小了。
然而,當你猜了數字 x 並且猜錯了的時候,你需要支付金額為 x 的現金。直到你猜到我選的數字,你才算贏得了這個遊戲。
示例:
n = 10, 我選擇了8. 第一輪: 你猜我選擇的數字是5,我會告訴你,我的數字更大一些,然後你需要支付5塊。給定 n ≥ 1,計算你至少需要擁有多少現金才能確保你能贏得這個遊戲。第二輪: 你猜是7,我告訴你,我的數字更大一些,你支付7塊。
第三輪: 你猜是9,我告訴你,我的數字更小一些,你支付9塊。
遊戲結束。8 就是我選的數字。
你最終要支付 5 + 7 + 9 = 21 塊錢。
答案:
public
static
intgetmoneyamount
(int n)
public
static
intdp
(int left,
int right)
return res;
}
解析:在數字1-n之間,假如我們選擇了x,陣列就會分成3個部分,[1,x-1],x,[x+1,n]。那麼會有3種情況,第一種我們選中了,所以這時候花費現金最少,第二種是我們選大了,第三種是我們選小了,用函式f(m,n)表示從數字m到n中所花費的最小金額,如果選擇了在範圍(i,j)中保證所花費最少(i<=x<=j),我們有下面這樣乙個公式。money=x+max(f(i,x-1)+f(x+1,j));**第10行我們找的是最大值,因為題目說了至少花費多錢現金才能贏得遊戲,我們只需要找到所有的花費最大值中的最小值即可。但是上面**效率明顯不是很高,因為遞迴的原因會出現重複計算,我們只需要用乙個臨時陣列儲存每次計算的結果,防止重複計算即可,我們來優化一下
public
static
intgetmoneyamount
(int n)
public
static
intdp
(int
table,
int left,
int right)
table[left]
[right]
= res;
return res;
}
除了遞迴的寫法以外,我們還可以使用動態規劃的方式解決,先看一下**
public
intgetmoneyamount
(int n)
table[j]
[i]= j +
1== i ? j : globalmin;}}
return table[1]
[n];
}
前兩個for迴圈會組成乙個封閉的空間[j,i],然後第3個for迴圈再從這個封閉的空間中找出所有花費最大值的最小值即可,這個最小值也只不過是在區間[j,i]之間的,然後通過外面兩層的for迴圈最終會找出區間[1,n]的值。第10行表示如果j和i僅僅相差1的話,那麼第3個for迴圈根本就不會執行,我們要猜最小的才能花費最少,所以選擇j。下面來畫個圖加深一下理解
這裡我們來舉個例子簡單說下,比如n等於5,為什麼只需要6塊錢就一定能贏得遊戲,結合上面的分析,我們知道當我們先猜2,或者4的時候結果都是6,我們以先猜2來分析一下,
1,如果選擇的是1,我們猜2,說明大了,下一步直接猜1就行了,所以只花了2塊錢。
2,如果選擇的是2,我們猜2,說明猜對了,一分沒花。
3,如果選擇的是3,我們猜2,說明猜小了,下一步猜4,說明大了,在下一步直接猜3,猜對了,所以總共花了2+4=6塊錢。
4,如果選擇的是4,我們猜2,說明猜小了,下一步猜4,猜中了,只花了2塊錢。
5,如果選擇的是5,我們猜2,說明猜小了,下一步猜4,又小了,在下一步直接猜5,猜對了,所以總共花了2+4=6塊錢。
綜上所述,當n等於5的時候,我們只需要6塊錢就一定能贏,
思考:
這題我估計很多人都聽說過,或者看過類似的這種題,很多時候我們猜這樣的題都喜歡從中間來猜,顯然通過上面的分析,如果我們從中間猜不一定會有最優的結果,比如當n=5的時候,當我們選擇4,或者5的時候,如果我們從中間來猜,先猜3,小了,再猜4,這時候無論是猜對了還是猜小了,所花費的肯定是大於6的,很明顯不是最優解。
375 猜數字大小 II
我們正在玩乙個猜數遊戲,遊戲規則如下 我從1到n之間選擇乙個數字,你來猜我選了哪個數字。每次你猜錯了,我都會告訴你,我選的數字比你的大了或者小了。然而,當你猜了數字 x 並且猜錯了的時候,你需要支付金額為 x 的現金。直到你猜到我選的數字,你才算贏得了這個遊戲。示例 n 10,我選擇了8.第一輪 你...
375 猜數字大小 II
我們正在玩乙個猜數遊戲,遊戲規則如下 我從1到n之間選擇乙個數字,你來猜我選了哪個數字。每次你猜錯了,我都會告訴你,我選的數字比你的大了或者小了。然而,當你猜了數字 x 並且猜錯了的時候,你需要支付金額為 x 的現金。直到你猜到我選的數字,你才算贏得了這個遊戲。示例 n 10,我選擇了8.第一輪 你...
375 猜數字大小 II
我們正在玩乙個猜數遊戲,遊戲規則如下 我從 1 到 n 之間選擇乙個數字,你來猜我選了哪個數字。每次你猜錯了,我都會告訴你,我選的數字比你的大了或者小了。然而,當你猜了數字 x 並且猜錯了的時候,你需要支付金額為 x 的現金。直到你猜到我選的數字,你才算贏得了這個遊戲。示例 n 10,我選擇了8.第...