LeeCode 1467 dfs + 组合数

58 篇文章 0 订阅
题意

传送门 LeeCode 1467. 两个盒子中球的颜色数相同的概率

题解

d f s ( i , l s u m , l c o ) dfs(i,lsum,lco) dfs(i,lsum,lco) 为已处理前 i − 1 i-1 i1 种颜色小球,当前第 1 1 1 个盒子小球数量为 l s u m lsum lsum,第 1 1 1 个盒子与第 2 2 2 个盒子颜色总数差值为 l c o lco lco 时,最终转移到合法状态的概率。

对于第 i i i 种颜色的小球,枚举放 0 0 0 b a l l s [ i ] balls[i] balls[i] 个小球到第一个盒子的情况,设此数量为 n n n,向下一种颜色小球转移的概率为 C b a l l s [ i ] n / 2 b a l l s [ i ] C_{balls[i]}^{n}/2^{balls[i]} Cballs[i]n/2balls[i],则

l c o i + 1 = { − 1 n = 0 1 n = b a l l s [ i ] 0 o t h e r w i s e lco_{i+1}=\begin{cases} -1&n=0\\ 1&n=balls[i]\\ 0&otherwise\\ \end{cases} lcoi+1=110n=0n=balls[i]otherwise

d f s ( i , l s u m , l c o ) = ∑ C b a l l s [ i ] n / 2 b a l l s [ i ] d f s ( i + 1 , l s u m + n , l c o i + 1 ) dfs(i,lsum,lco)=\sum C_{balls[i]}^{n}/2^{balls[i]}dfs(i+1,lsum+n,lco_{i+1}) dfs(i,lsum,lco)=Cballs[i]n/2balls[i]dfs(i+1,lsum+n,lcoi+1)

d f s dfs dfs 求得的结果是两个盒子小球数相同且球的颜色数相同的概率,设为 P ( x ) P(x) P(x);而题意为求两个盒子小球数相同时,两个盒子球的颜色数相同的条件概率;设两个盒子小球数相同的概率为 P ( y ) P(y) P(y),小球总数为 s u m sum sum

P ( y ) = C s u m s u m / 2 2 s u m P(y)=\frac{C_{sum}^{sum/2}}{2^{sum}} P(y)=2sumCsumsum/2

则答案为

P ( x ∣ y ) = P ( x y ) P ( y ) = P ( x ) P ( y ) P(x|y)=\frac{P(xy)}{P(y)}=\frac{P(x)}{P(y)} P(xy)=P(y)P(xy)=P(y)P(x)

class Solution
{
public:
    int C[7][7];
    int fac[7], n, half;
    vector<int> balls;
    void init()
    {
        fac[0] = 1;
        for (int i = 1; i < 7; i++)
            fac[i] = 2 * fac[i - 1];
        for (int i = 0; i < 7; i++)
            C[i][0] = 1;
        for (int i = 1; i < 7; i++)
        {
            for (int j = 1; j < 7; j++)
            {
                C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
            }
        }
    }
    double dfs(int b, int lnum, int lco)
    {
        if (lnum > half)
            return 0;
        if (b == n)
            return lnum == half ? (lco == 0 ? 1 : 0) : 0;
        double res = 0, m = fac[balls[b]];
        for (int i = 0; i <= balls[b]; i++)
        {
            if (i == 0)
            {
                res += 1.0 / m * dfs(b + 1, lnum, lco - 1);
            }
            else if (i == balls[b])
            {
                res += 1.0 / m * dfs(b + 1, lnum + i, lco + 1);
            }
            else
            {
                res += C[balls[b]][i] / m * dfs(b + 1, lnum + i, lco);
            }
        }
        return res;
    }
    double fact(int l, int r)
    {
        if (l == r)
            return l;
        return l * fact(l - 1, r);
    }
    double calc(int n)
    {
        double sum = 1;
        for (int i = 0; i < n; i++)
            sum *= 2;
        double c = fact(n, n / 2 + 1) / fact(n / 2, 1);
        return c / sum;
    }
    double getProbability(vector<int> &balls)
    {
        init();
        int n = balls.size(), sum = 0;
        for (int i = 0; i < n; i++)
            sum += balls[i];
        this->n = n, this->half = sum / 2, this->balls = balls;
        double p = calc(sum);
        return dfs(0, 0, 0) / p;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值