[51nod 1450] 闯关游戏

来源:互联网 发布:高级数据库系统与实现 编辑:程序博客网 时间:2024/06/07 05:06

题目描述

一个游戏App由N个小游戏(关卡)构成,将其标记为0,1,2,..N-1。这些小游戏没有相互制约的性质,玩家可以任意时刻玩任意一个小游戏,且每个小游戏可以玩任意多次,一个小游戏玩一次消耗玩家恰好1min的时间。每个小游戏会根据玩家的表现返回3种结果:1)挑战失败;2)挑战成功并获得1颗星;3)挑战成功且获得2颗星。玩家可以多次挑战同一个小游戏,而且系统会记录玩家多次挑战中的最好成绩。(注意:两颗星优于一颗星优于挑战失败。)
这个游戏App通关需要同时满足2个条件:1)N个小游戏的系统记录的最好成绩都是成功;2)这N个小游戏的系统记录成绩中的星星总数至少是M颗。
根据一些统计,一个玩家在任一次玩第i个小游戏时,都会独立的发生以下结果:
* 有(1000 - X[i] - Y[i])*0.001的概率会挑战失败;
* 有 X[i]*0.001 的概率会挑战成功并获得一颗星;
* 有 Y[i]*0.001 的概率会挑战成功并获得两颗星.
其中1<=X[i],Y[i],且X[i]+Y[i]<=1000,且都为整数.
问一个玩家从安装完这个游戏App到这个游戏App通关,最优策略下需要花费时间的期望E。输出E的值,以min为该时间单位。(误差在1e-7内)

例如:样例中有两个小游戏,且两个小游戏每次玩必能通过,且有0.5的概率拿两颗星。玩家可以先各玩一个小游戏一次,有0.75的概率能拿至少3颗星;有0.25的概率只能拿2颗星,此时需要盯着一关不停的玩,直到得到两颗星,这需要1/2 * 1 + 1/4 * 2 + 1/8 * 3 + … + 1/(2^k) * k + …. 次。所以,E = 0.75*2 + 0.25*(2 + 1/2 * 1 + 1/4 * 2 + 1/8 * 3 + … + 1/(2^k) * k + …. )= 2.5。

分析

我们可以先搞出每个游戏挑战成功和一定获得两颗星的期望,因为必定有一些点要搞两颗星,每个游戏都必须要成功。
额…好久没打期望题,复习一下解方程…设两颗星期望为x,x=1Y[i]1000+x(1Y[i]1000),那么x=1000Y[i]
现在考虑怎么求总的期望。
你肯定不能说有一些一定两颗星,一些一定一颗星来分配方案,因为有时候你想要分配一颗星的地方可能爆出两颗星,那么期望肯定大了。
我们发现当要求一些点只求成功的时候,一颗星或者两颗星的概率是固定的,那么我们如果按照一定的顺序只求成功,到最后就要全部取两颗星了。哎,考虑让两颗星的期望最小,我们发现按照Y排序,这样的顺序,取两颗星的期望和最小。那么前面的部分,考虑记录一些状态来储存所有局面,设f[i][j]表示玩了前i个游戏,获得j颗星的期望(已经乘上概率,最后统计答案直接加上即可),g[i][j]表示到达这个局面的概率。那么你就可以递推了。在mj=(ni)2的时候,后面就要全部取两颗星了,不用再转移了。只求成功的时候,一颗星和两颗星的概率比例是X[i]:Y[i]的,这样就解决了。

#

 #include<cstdio> #include<algorithm>#include<cstring>#include<cmath>#include<set>using namespace std;typedef long long ll;typedef double db;#define fo(i,j,k) for(i=j;i<=k;i++)#define fd(i,j,k) for(i=j;i>=k;i--)#define cmin(a,b) (a=(a<b)?a:b)#define cmax(a,b) (a=(a>b)?a:b)const int N=4000+5;db s1[N],s2[N],p1[N],p2[N],ans; db f[2][N],g[2][N];int X[N],Y[N],n,m,i,j,d[N],q1,q2;bool cmp(int x,int y){    return Y[x]<Y[y];}int main(){    freopen("t1.in","r",stdin);    //freopen("t1.out","w",stdout);    scanf("%d %d",&n,&m);    fo(i,1,n) scanf("%d %d",&X[i],&Y[i]),d[i]=i;    sort(d+1,d+1+n,cmp);    fo(j,1,n)    {        i=d[j];        s1[j]=1000.0/db(X[i]+Y[i]);        s2[j]=1000.0/db(Y[i]);        p1[j]=db(X[i])/db(X[i]+Y[i]);;        p2[j]=db(Y[i])/db(X[i]+Y[i]);;    }    fd(i,n-1,1) s2[i]+=s2[i+1];    ans=0;    f[0][0]=0;    g[0][0]=1.0;    q1=0;    q2=1;    fo(i,0,n-1)    {        fo(j,0,i*2)        if (g[q1][j]!=0.0)        {            if ((n-i)*2==m-j)                ans+=g[q1][j]*s2[i+1]+f[q1][j];            else            {                f[q2][j+1]+=(f[q1][j]+s1[i+1]*g[q1][j])*p1[i+1];                g[q2][j+1]+=g[q1][j]*p1[i+1];                f[q2][j+2]+=(f[q1][j]+s1[i+1]*g[q1][j])*p2[i+1];                g[q2][j+2]+=g[q1][j]*p2[i+1];            }        }        fo(j,0,i*2) f[q1][j]=g[q1][j]=0;        q1^=1;        q2^=1;    }    fo(j,m,i*2)         ans+=f[q1][j];    printf("%.7lf",ans);} 
原创粉丝点击