入门力扣自学笔记202 C++ (题目编号:808)

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。返回值在正确答案 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


来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/soup-servings
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


思路:

首先,我们可以发现,这些都是25的倍数,所以所有的都除25即可,如果出现26,那么就进1,所以在进行除25的时候,先加24再除,可以解决进1的问题。

其次,我们发现会出现4中情况,第一种就是AB都没了,这种最后返回为0.5,第二种是A没了,这种为1,第三种是B没了,这种为0,第四种是AB都还有,这种直接返回剩余量即可。

最后,我们进行递归,返回最后答案即可,但是千万注意,这道题用记忆化搜索的时候,会越界,我们发现当数目特别大的时候,最后返回值会无限趋近于1,所以精剪一下,控制为4800即可(这里4800是根据经验所得,多试一试)。


代码:

class Solution {
public:
    double soupServings(int n) {
        double f[200][200] = {0.0};
        function dfs = [&](int i,int j) -> double
        {
            if(i <= 0 && j <= 0)
                return 0.5;
            if(i <= 0)
                return 1;
            if(j <= 0)
                return 0;
            if(f[i][j] > 0)
                return f[i][j];
            double ans = 0.25 * (dfs(i-4,j) + dfs(i-3,j-1) + dfs(i-2,j-2) + dfs(i-1,j-3));
            f[i][j] = ans;
            return ans;
        };
        return n > 4800 ? 1 : dfs((n + 24) / 25 , (n + 24) / 25);
    }
};

你可能感兴趣的:(力扣算法学习,c++,leetcode,算法)