808. 分湯
有 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 的範圍將被認爲是正確的。
class Solution {
//都是25的倍數,我們可以除先25
public double soupServings(int N) {
if(N>=4800) {
return 1.0;
}
int n=(int)Math.ceil(N/25.0);
double[][] dp=new double[n+1][n+1];
//特殊條件
dp[0][0]=0.5;
for(int i=1;i<n+1;i++) {
dp[i][0]=0;
dp[0][i]=1;
}
for(int i=1;i<n+1;i++) {
int a1=i-4>0?i-4:0;
int a2=i-3>0?i-3:0;
int a3=i-2>0?i-2:0;
int a4=i-1>0?i-1:0;
for(int j=1;j<n+1;j++) {
int b1=j;
int b2=j-1>0?j-1:0;
int b3=j-2>0?j-2:0;
int b4=j-3>0?j-3:0;
dp[i][j]=0.25*(dp[a1][b1]+dp[a2][b2]+dp[a3][b3]+dp[a4][b4]);
}
}
return dp[n][n];
}
}