jzoj2754 【2012东莞市选】时间流逝 (概率,赌徒破产问题)

题面

   生活可以很简单。可以探索水底世界的神秘,也可以去发现奇特新生物,亦或踏上一段新生的旅程。在必须要迎接挑战或跟周围的生物进行生存争夺之前,享受自由的飞翔。此时你会觉得生活是如此美好。
  像蛇喜欢吃浮游生物一样(哦,我好像忘记告诉你这个常识),每天,你可以吃一些你周围的基础生物,然后会在你的尾巴上得到一个能量圈。你将会有好多种不同的能量圈,每一个都会被赋予一个能量。你可以拥有多个同种的能量圈,但是对于新得到的能量圈,它的能量不能大于你已拥有的任何一个能量圈。在前面规则的前提下,获得新的能量圈的种类的概率是一样的。一天天过去,你得到越来越多的能量,开始了进化演变。
   但是你也有自己的问题,有时你会面对邪恶的果冻鱼。它会追着你咬你,你不得不扔出最小能量值的能量圈然后赶忙逃跑。在这种情况下,你不会有任何的胃口了,因此这天你将不再得到任何能量圈。幸好,当你没有任何能量圈的时候,果冻鱼就算看见你也不会追着你,此时你可以好好地享用美食。
  你听说当你的总的能量值超过了某个阈值之后,可以进化成强大模式并能够吃掉果冻鱼。是时候反击了!下面是本题的问题:预计要过多少天你才能进化成强大模式?(第一天默认你没有任何能量圈)  

对于所有数据,0.1≤P≤0.9,1≤T≤50,1≤N≤30。

分析

这题很日!首先设
令f表示总和为y,剩余物品为z的某一种确切方案,到结束的期望天数.
我们只需要求当y=0,z=n时的f即可(因为只有一种方案嘛)

f=(fa+1)p+(f+1)1pz
fa是f的前项(fa取一个转移到f),f’是f的后项 (这里有点难理解,具体来说就是:
先要求f,然后f又要求其他..依次类推….
当前可能会
1.退一个,回到fa
2.进一个,新f’

假如我们可以用A*f+B表示 f
那么就可以用fa表示f,也就是f=fa*A+B,到最后就是A*不存在+B=f[0][1]。
终点就是如果y>T则显然期望是0。

又因为f[0][1]没有前项转移,所以就可以求得f[0][1].
其实就是赌徒破产问题的一个变形。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 35;
typedef double db;
db P,ans;
int T,n,a[N];
struct node{db A,B;};
node jy[55][N];
node operator+(node a,node b) {return (node){a.A+b.A,a.B+b.B};}
node operator+(node a,int b) {return (node){a.A,a.B+b};}
node operator*(node a,db b) {return (node){a.A*b,a.B*b};}
node dfs(int s,int x,int dep)  {
    if (s>T) return (node){0,0};
    if (jy[s][x].A + jy[s][x].B !=0) return jy[s][x];
    node now=(node){0,0};
    for (int i=1; i<=x; i++) now=now+(dfs(s+a[i],i,dep+1)+1);
    if (s==0) {
        now=now*(1.0/x);
        return jy[s][x]=(node){0,now.B/(1-now.A)};
    } else {
        now=now*((1-P)/x);
        return jy[s][x]=(node){P/(1-now.A),(now.B+P)/(1-now.A)};
    }
}

int main() {
    freopen("1.in","r",stdin);
    while (scanf("%lf %d %d",&P,&T,&n)!=EOF) {
        for (int i=1; i<=n; i++) scanf("%d",&a[i]);
        sort(a+1,a+1+n);
        printf("%.3lf\n",dfs(0,n,0).B);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值