目录链接:
力扣编程题-解法汇总_分享+记录-CSDN博客
GitHub同步刷题项目:
https://github.com/September26/java-algorithms
原题链接:力扣
描述:
有 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。返回值在正确答案 10-5
的范围内将被认为是正确的。
示例 1:
输入: n = 50 输出: 0.62500 解释:如果我们选择前两个操作,A 首先将变为空。 对于第三个操作,A 和 B 会同时变为空。 对于第四个操作,B 首先将变为空。 所以 A 变为空的总概率加上 A 和 B 同时变为空的概率的一半是 0.25 *(1 + 1 + 0.5 + 0)= 0.625。
示例 2:
输入: n = 100 输出: 0.71875
提示:
0 <= n <= 109
解题思路:
* 借鉴的官方题解中的思路, * 使用dp[a][b]来记录还剩余a和b容量时,最后的结果。 * a=0,b=0时,肯定同时分配完成,则结果为1*0.5=0.5。 * a>0,b=0时,a分配完成b还没有,则结果为1。 * 然后反向推不同剩余量时的概率。N=n/25,则一共有个N*N种可能,依次遍历所有可能行。 * 举个例子,dp[4][0]的来源一共有4种,dp[0][0]/dp[1][3]/dp[2][2]/dp[3][1] * 我们根据已有的参数,反求a>0,b>0时的场景即可。
代码:
public class Solution808 {
public double soupServings(int n) {
n = (int) Math.ceil((double) n / 25);
if (n >= 179) {
return 1.0;
}
double[][] dp = new double[n + 1][n + 1];
dp[0][0] = 0.5;
for (int b = 1; b <= n; b++) {
dp[0][b] = 1;
}
for (int a = 1; a <= n; a++) {
for (int b = 1; b <= n; b++) {
dp[a][b] = 0.25 * (dp[Math.max(0, a - 4)][b] + dp[Math.max(0, a - 3)][Math.max(0, b - 1)] + dp[Math.max(0, a - 2)][Math.max(0, b - 2)] + dp[Math.max(0, a - 1)][Math.max(0, b - 3)]);
}
}
return dp[n][n];
}
}