题目地址:
https://leetcode.com/problems/soup-servings/description/
有两种汤:
A
A
A型和
B
B
B型。初始时有
n
n
n毫升的每种类型的汤。有四种操作方式:
1、提供
100
100
100毫升
A
A
A型汤和
0
0
0毫升
B
B
B型汤;
2、提供
75
75
75毫升
A
A
A型汤和
25
25
25毫升
B
B
B型汤;
3、提供
50
50
50毫升
A
A
A型汤和
50
50
50毫升
B
B
B型汤;
4、提供
25
25
25毫升
A
A
A型汤和
75
75
75毫升
B
B
B型汤。
我们将以
0.25
0.25
0.25的相等概率从四种操作中选择一种。如果剩余的汤量不足以完成操作,将全部提供。一旦汤不够了就停止。返回
A
A
A型汤首先用完的概率,加上
1
2
\frac{1}{2}
21的A型和B型同时用完的概率。在实际答案的
1
0
−
5
10^{-5}
10−5范围内的答案都可以接受。
思路是记忆化搜索,令 f ( i , j ) f(i, j) f(i,j)表示当前还剩下 i , j i, j i,j的数量的 A , B A,B A,B的汤的情况下, A A A型汤首先用完的概率,加上 1 2 \frac{1}{2} 21的A型和B型同时用完的概率。然后用全概率公式进行记忆化搜索。代码如下:
class Solution {
public:
using PII = pair<int, int>;
double soupServings(int n) {
if (n >= 4800) return 1;
n = (n + 24) / 25;
auto ha = [&](auto& p) {
return hash<int>()(p.first) ^ hash<int>()(p.second);
};
unordered_map<PII, double, decltype(ha)> mp(0, ha);
return dfs(n, n, mp);
}
double dfs(int x, int y, auto& mp) {
if (x <= 0 && y <= 0) return 0.5;
if (x <= 0) return 1;
if (y <= 0) return 0;
if (mp.count({x, y})) return mp[{x, y}];
return mp[{x, y}] = (dfs(x - 4, y, mp) + dfs(x - 3, y - 1, mp) +
dfs(x - 2, y - 2, mp) + dfs(x - 1, y - 3, mp)) /
4.0;
}
};
时空复杂度 O ( n 2 ) O(n^2) O(n2),实际时间不会这么多。