友情支持

如果您觉得这个笔记对您有所帮助,看在D瓜哥码这么多字的辛苦上,请友情支持一下,D瓜哥感激不尽,😜

支付宝

微信

有些打赏的朋友希望可以加个好友,欢迎关注D 瓜哥的微信公众号,这样就可以通过公众号的回复直接给我发信息。

wx jikerizhi

公众号的微信号是: jikerizhi因为众所周知的原因,有时图片加载不出来。 如果图片加载不出来可以直接通过搜索微信号来查找我的公众号。

808. 分汤

A 和 B 两种类型 的汤。一开始每种类型的汤有 n 毫升。有四种分配操作:

  1. 提供 100ml汤A0ml汤B

  2. 提供 75ml汤A25ml汤B

  3. 提供 50ml汤A50ml汤B

  4. 提供 25ml汤A75ml汤B

当我们把汤分配给某人之后,汤就没有了。每个回合,我们将从四种概率同为 0.25 的操作中进行分配选择。如果汤的剩余量不足以完成某次操作,我们将尽可能分配。当两种类型的汤都分配完时,停止操作。

注意不存在先分配 100 ml 汤B 的操作。

需要返回的值: 汤A 先分配完的概率 + 汤A和汤B 同时分配完的概率一半。返回值在正确答案 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

思路分析

没想到竟然是动态规划!将想得到指定数量的解,那么可以从四种情况来获取:即减去对应数量的值。又因为每次操作都是 25 的倍数,所以,可以把原始数字除以 25 向上取整。如下图:

0808 10
0808 11
  • 一刷

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
 * @author D瓜哥 · https://www.diguage.com
 * @since 2026-07-03 22:51:51
 */
public double soupServings(int n) {
  if (n >= 4451) {
    return 1;
  }
  n = (n + 24) / 25;
  double[][] memo = new double[n + 1][n + 1];
  return dfs(n, n, memo);
}

private double dfs(int a, int b, double[][] memo) {
  if (a <= 0 && b <= 0) {
    return 0.5D;
  }
  if (a <= 0) {
    return 1;
  }
  if (b <= 0) {
    return 0;
  }
  if (memo[a][b] != 0) {
    return memo[a][b];
  }
  return memo[a][b] = (dfs(a - 4, b, memo) + dfs(a - 3, b - 1, memo)
    + dfs(a - 2, b - 2, memo) + dfs(a - 1, b - 3, memo)) / 4;
}