分汤
难度:
标签:
题目描述
代码结果
运行时间: 32 ms, 内存: 17.6 MB
/*
* 思路:
* 使用Java Stream的方式实现相同的逻辑。
* 我们依然用dp数组来记录每个状态的概率,并通过流式操作计算dp[n][n]。
*/
import java.util.stream.IntStream;
public class SoupServingsStream {
public double soupServings(int n) {
if (n > 5000) return 1.0;
int size = (n + 24) / 25;
double[][] dp = new double[size + 1][size + 1];
IntStream.rangeClosed(0, size).forEach(i -> {
IntStream.rangeClosed(0, size).forEach(j -> {
if (i == 0 && j == 0) {
dp[i][j] = 0.5;
} else if (i == 0) {
dp[i][j] = 1.0;
} else if (j == 0) {
dp[i][j] = 0.0;
} else {
dp[i][j] = 0.25 * (getDP(dp, i - 4, j) + getDP(dp, i - 3, j - 1) + getDP(dp, i - 2, j - 2) + getDP(dp, i - 1, j - 3));
}
});
});
return dp[size][size];
}
private double getDP(double[][] dp, int i, int j) {
if (i < 0) i = 0;
if (j < 0) j = 0;
return dp[i][j];
}
}
解释
方法:
这个题解采用了记忆化搜索(动态规划的一种形式)来解决问题。首先,将毫升数转换为以25毫升为单位的较小值以简化计算。当汤的量n足够大时(n>=179),直接返回1.0,因为在这种情况下,几乎总是汤A会先分配完或者与汤B同时分配完。对于较小的n,使用深度优先搜索(DFS)递归地计算四种分配操作的概率,使用装饰器cache来存储已计算的结果,避免重复计算。最终的概率由四个递归调用的平均值决定,分别对应四种不同的操作。递归的边界条件处理了汤A或汤B先分配完以及同时分配完的情况。
时间复杂度:
O(n^2)
空间复杂度:
O(n^2)
代码细节讲解
🦆
为什么在n大于等于179时,可以近似认为概率为1.0?是否有数学证明或实验数据支持这一点?
▷🦆
在记忆化搜索中,使用了`@cache`装饰器。能否详细说明其工作原理及对算法性能的具体影响?
▷🦆
递归函数`dfs`在处理边界条件时,为何当`a <= 0 and b <= 0`时返回0.5,这代表了什么意义?
▷