Leetcode808

有两个瓶子A和B分别有N毫升水,

每次可以进行下面四种操作之一

  1. Serve 100 ml of soup A and 0 ml of soup B
  2. Serve 75 ml of soup A and 25 ml of soup B
  3. Serve 50 ml of soup A and 50 ml of soup B
  4. Serve 25 ml of soup A and 75 ml of soup B

求先倒完A的概率+0.5*(同时倒完A和B的概率)

 

dp[a][b]为A瓶子有a毫升 B瓶子有b毫升的要求的那个结果

那么

dp[a][b] = 0.25 * (dp[a -100][b] + dp[a -75][b - 25] +dp[a -50][b -50] + dp[a -25][b - 75])

 

但是题目的N <= 10^9

注意到题目的四个操作,是没有直到B瓶的操作的,那么随着N的增大,先倒完A瓶的概率越来越大,结果应该是越来越大的。

通过计算一定的值来发现当N > =N0的时候,结果和1差的很小的时候直接返回1即可,题目允许有误差。

 

同时为了计算方便,可以以25为一个单位,不影响最终的结果。

 

    double[][] memory;
    public double soupServings(int N) {
        N = (N + 24) / 25;
        if (N >= 500) return 1.0;
        memory = new double[500][500];
        return f(N, N);
    }


    double f(int a, int b) {
        if (a <= 0 && b <= 0) return 0.5;
        if (a <= 0) return 1.0;
        if (b <= 0) return 0;
        if (memory[a][b] > 0) return memory[a][b];
        double res = 0;
        res += f(a - 4, b);
        res += f(a - 3, b - 1);
        res += f(a - 2, b - 2);
        res += f(a - 1, b - 3);
        res *= 0.25;
        memory[a][b] = res;
        return res;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值