一、题目描述
题目链接:https://leetcode-cn.com/problems/soup-servings/
二、题目分析
还有评论:https://leetcode-cn.com/problems/soup-servings/comments/
题目把我看得一愣一愣的,看好久都不知道要干嘛。就是说我们每次提供N份A汤,N份B汤,然后把汤倒掉(我觉得这样说比较好理解),然后有四个倒的策略:
1、A倒100份,B不倒
2,A倒75份,B倒25份
3,A倒50份,B倒50份
4、A倒25份,B倒75份
这里我们可以使用一个二维数组dp[i][j]来表示当有i份A汤和j份B汤倒掉后得出的概率。当我们计算dp[i][j]的时候,用dp[i - 100][j]来表示A汤倒掉100份对应的概率,dp[i - 75][j - 25]来表示A汤倒掉75份,B汤倒掉25份对应的概率,dp[i-50][j-50],dp[i-25][j-75]同理,然后把四个概率加起来*0.25,就是dp[i][j]。因此我们是一个从前往后的dp。
三、代码
public double soupServings(int N) {
// 这里看题解说是经过数学验证的,那就,这样吧
if(N>=4800)return 1;
// 这里是一个trick,因为按照题目,倒掉的汤基数是25,因此我们可以缩小N的范围
// 余数如果不为0我们也当成1份算
N=N/25+((N%25==0)?0:1);
double dp[][]=new double[N+1][N+1];
// 当A汤为0时,A汤一定先倒完
Arrays.fill(dp[0],1);
// 除非B汤也为0
dp[0][0]=0.5;
for(int i=1;i<=N;i++){
for(int j=1;j<=N;j++){
dp[i][j]=0.25*(dp[Math.max(0,i-4)][j]+dp[Math.max(0,i-3)][Math.max(0,j-1)]+dp[Math.max(0,i-2)][Math.max(0,j-2)]+dp[Math.max(0,i-1)][Math.max(0,j-3)]);
}
}
return dp[N][N];
}