LeetCode 分湯(動態規劃 記憶搜尋)

2021-09-22 22:31:31 字數 2784 閱讀 7380

有 a 和 b 兩種型別的湯。一開始每種型別的湯有 n 毫公升。有四種分配操作:

提供 100ml 的湯a 和 0ml 的湯b。

提供 75ml 的湯a 和 25ml 的湯b。

提供 50ml 的湯a 和 50ml 的湯b。

提供 25ml 的湯a 和 75ml 的湯b。

當我們把湯分配給某人之後,湯就沒有了。每個回合,我們將從四種概率同為0.25的操作中進行分配選擇。如果湯的剩餘量不足以完成某次操作,我們將盡可能分配。當兩種型別的湯都分配完時,停止操作。

注意不存在先分配100 ml湯b的操作。

需要返回的值: 湯a先分配完的概率 + 湯a和湯b同時分配完的概率 / 2。

示例:

輸入: n = 50

輸出: 0.625

解釋:如果我們選擇前兩個操作,a將首先變為空。對於第三個操作,a和b會同時變為空。對於第四個操作,b將首先變為空。

所以a變為空的總概率加上a和b同時變為空的概率的一半是 0.25 *(1 + 1 + 0.5 + 0)= 0.625。

注意:

0 <= n <= 10^9。

返回值誤差在 10^-6 的範圍將被認為是正確的。

思路分

析:\color思路分析:

思路分析

:這道題還是有點難度的,首先我們需要將n縮小一些。

第一,四種分發基數都是25,即如果不足25按照25繼續分,那麼我們可以將n縮小為原來的25分之一。

第二,n的範圍是[0, 109],這是乙個特別大的數字了。並且提示中註明當我們返回的結果與真實誤差小於10-6的時候,就算正確。而當n趨向於無窮大時,a先被分完以及a和b同時被分完的概率會無限接近於1。經過嚴格計算我們知道當n >= 4800之後,返回的概率值與1的差距就小於10-6了。所以當n >= 4800的時候,我們就直接返回1。

第三,動態陣列dp[i][j]表示:當給定i毫公升的a和j毫公升的b,湯a先分配完的概率 + 湯a和湯b同時分配完的概率 / 2

轉移方程:dp[i][j] = 0.25 * (dp[i-100][j] + dp[i-75][j-25] + dp[i-50][j-50] + dp[i-75][j-25])

將n縮小為原來的25分之一的轉移方程:dp[i][j] = 0.25 * (dp[i-4][j] + dp[i-3][j-1] + dp[i-2][j-2] + dp[i-3][j-1])

class

solution

int myn =

(int

)ceil

(n /

25.0);

//縮小為原來的25分之一

//dp[i][j]表示:當給定i毫公升的a和j毫公升的b,湯a先分配完的概率 + 湯a和湯b同時分配完的概率 / 2

vector

double

>>

dp(myn +

1, vector<

double

>

(myn +1,

0));

dp[0]

[0]=

0.5;

//特殊情況,0毫公升a、0毫公升b(同時分配完 1 * 0.5)

for(

int i =

1; i < myn +1;

++i)

//開始動態規劃

當然也可以使用帶備忘錄的搜尋演算法。(有點像斐波拉契而數列)

class

solution

int myn =

(int

)ceil

(n /

25.0);

//縮小為原來的25分之一

mapint,

int>

,double

> hashmap;

//用於記錄的概率結果

leetcode 動態規劃

題目如下 給定乙個整型陣列,至少有乙個元素,請計算子陣列最大乘積是多少?子陣列必須是原陣列中連續的一串數字構成的陣列。整數可正可負。例如 給定陣列 2,3,2,4 經過計算,得到最大乘積為6。子陣列為 2,3 根據原貼的解題思路,這道題可以用動態規劃來解,但難度在 呢?負負得正,就可惡在這裡。那這個...

Leetcode 動態規劃

題目 原題鏈結在這裡 最長字串鏈。給乙個單詞列表,找乙個詞鏈,使得詞鏈後乙個單詞由前乙個單詞增加乙個字元得到,求最長詞鏈長度。解答 1 根據詞鏈的定義,短的單詞可以由長的單詞減去單詞中乙個字元得到。因此可以先對單詞列表,按照單詞的長度從大到小排序。2 單詞的最大長度為 16,因此可以對於每個單詞 w...

leetcode 動態規劃

題目 給定乙個包含非負整數的 m x n 網格,請找出一條從左上角到右下角的路徑,使得路徑上的數字總和為最小。每次只能向下或者向右移動一步。示例 輸入 1,3,1 1,5,1 4,2,1 輸出 7 解釋 因為路徑 1 3 1 1 1 的總和最小。思路 定義一維陣列dp用於記錄起始點到某一點最小距離,...