C. Need for Pink Slips

C. Need for Pink Slips

问题:一个游戏,给出 C , M , P C,M,P C,M,P三个事件,每个事件的概率是 c , m , p c,m,p cmp,当出现事件 P P P的时候,游戏结束。在每一轮游戏过程中 c , m , p c,m,p cmp都会根据规则发生变化。问游戏进行多少轮的期望。

规则:给定一个小数 v v v

  • ( c , m , p ) = ( 0.2 , 0.1 , 0.7 ) (c,m,p)=(0.2,0.1,0.7) (c,m,p)=(0.2,0.1,0.7) v = 0.1 v=0.1 v=0.1, 在发生事件C后,因为 c > v c>v c>v,所以 c = c − v , m = v / 2 + m , p = v / 2 + p c=c-v,m=v/2+m, p = v/2+p c=cvm=v/2+m,p=v/2+p ( c , m , p ) = ( 0.1 , 0.15 , 0.75 ) (c,m,p)=(0.1,0.15,0.75) (c,m,p)=(0.1,0.15,0.75).

  • ( c , m , p ) = ( 0.1 , 0.2 , 0.7 ) (c,m,p)=(0.1,0.2,0.7) (c,m,p)=(0.1,0.2,0.7) v = 0.2 v=0.2 v=0.2, 在发生事件C后,因为 c ≤ v c\le v cv,所以 c = 0 , m = c / 2 + m , p = c / 2 + p c=0,m=c/2+m, p = c/2+p c=0m=c/2+m,p=c/2+p ( c , m , p ) = ( 0 , 0.25 , 0.75 ) (c,m,p)=(0,0.25,0.75) (c,m,p)=(0,0.25,0.75).

  • ( c , m , p ) = ( 0.2 , 0 , 0.8 ) (c,m,p)=(0.2,0,0.8) (c,m,p)=(0.2,0,0.8) v = 0.1 v=0.1 v=0.1, 在发生事件C后,因为 c > v c>v c>v,但是 m = 0 m=0 m=0,所以 c = c − v , m = , p = v + p c=c-v,m=, p = v+p c=cvm=,p=v+p ( c , m , p ) = ( 0.1 , 0 , 0.9 ) (c,m,p)=(0.1,0,0.9) (c,m,p)=(0.1,0,0.9)

  • ( c , m , p ) = ( 0.1 , 0 , 0.9 ) (c,m,p)=(0.1,0,0.9) (c,m,p)=(0.1,0,0.9) v = 0.2 v=0.2 v=0.2, 在发生事件C后,因为 c ≤ v c\le v cv,但是 m = 0 m=0 m=0,所以 c = 0 , m = 0 , p = c + p c=0,m=0, p = c+p c=0m=0,p=c+p ( c , m , p ) = ( 0 , 0 , 1 ) (c,m,p)=(0,0,1) (c,m,p)=(0,0,1)

解答:期望=轮数*概率,根据规则, d f s dfs dfs每一种情况,都加起来就是答案,注意设置esp。

#include <bits/stdc++.h>

using namespace std;
// #define double long double
typedef long long ll;
const int N = 1e4+10;
const int mod = 1e9+7;
const double esp = 1e-12;
double s[10], v, ans = 0;
double i = 1;
//s数组存放c,m,p。ans是答案。
void dfs(double val) {
    //val表示出现当前情况的概率。
    if(val == 0 || val*s[3] < esp) return;
    else {
        //val*s[3]表示下一轮就是事件p发生,能对期望产生val*s[3]*i的贡献。
        ans += val*s[3]*i;
    }
    i += 1;
    double a = s[1], b = s[2], c = s[3];
    double tmp = val*a;
    if(a > 0) {
        //根据规则来计算下一轮c,m,p的值。
        if(a <= v) {
            s[1] = 0;
            if(s[2] < esp) s[3] = a + s[3];
            else s[2] = a/2 + s[2], s[3] = a/2 + s[3];
            
            dfs(val*a);
            s[1] = a, s[2] = b, s[3] = c;//回溯。
        }
        else {
            s[1] = a-v;
            if(s[2] < esp) s[3] += v;
            else s[2] = v/2 + s[2], s[3] = v/2 + s[3];
            dfs(val*a);
            s[1] = a, s[2] = b, s[3] = c;
        }
    }
    if(b > 0) {
        tmp = val * b;
        if(b <= v) {
            s[2] = 0;
            if(s[1] < esp) s[3] += b;
            else s[1] = b/2+s[1] , s[3] = b/2 + s[3];
            dfs(val*b);
            s[1] = a, s[2] = b, s[3] = c;
        }
        else {
            s[2] = b-v;
            if(s[1] < esp) s[3] += v;
            else s[1] = v/2+s[1], s[3] = v/2 + s[3];
            dfs(val*b);
            s[1] = a, s[2] = b, s[3] = c;
        }
    }
    i -= 1;
}
int main() {
#ifndef ONLINE_JUDGE 
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif 
    int t;
    cin >> t;
    while(t--) {
        ans = 0, i = 1;
        for(int i=1; i<=3; i++) cin >> s[i];
        cin >> v;
        dfs(1);
        printf("%.12lf\n", ans);
   }
}   

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值