51nod 1450 闯关游戏

来源:互联网 发布:贵州浪人网络投诉 编辑:程序博客网 时间:2024/06/07 16:31

一个游戏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。
Input
第一行两个个整数N,M,且1<=N<=2000,N <= M <= 2N接下来N行,每行两个整数,X[i]、Y[i],其中1<=X[i],Y[i],且X[i]+Y[i]<=1000
Output
一个浮点数,即期望E。确保E的精度与正解的绝对误差或相对误差小于1e-7。
Input示例
2 3500 500500 500
Output示例
2.5
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

期望DP~

,拖了一天,结果还是抄了尹神的呢。

我们先把m-=n,表示至少有m个是两颗星

用f[i][j]表示还有i个没有挑战过,还有j个必须是2颗星的期望,那么我们分开更新即可。

但是照这种更新方式的话,完全不需要排序使得后面的m个必须是2颗星啊。


#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;int n,m,k;double f[2001][2001];struct node{double x,y;bool operator < (const node&u){return y<u.y;}}a[2001];int main(){scanf("%d%d",&n,&m);m-=n;for(int i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y);sort(a+1,a+n+1);for(int i=0;i<m;i++) f[n][i]=999999999;for(int i=n-1;~i;i--){for(int j=0;j<m;j++)  f[i][j]=min(  1000/(a[i+1].x+a[i+1].y)+a[i+1].x/(a[i+1].x+a[i+1].y)*f[i+1][j]  +a[i+1].y/(a[i+1].x+a[i+1].y)*f[i+1][j+1],  1000/a[i+1].y+f[i+1][j+1]);f[i][m]=1000/(a[i+1].x+a[i+1].y)+f[i+1][m];}printf("%.8lf\n",f[0][0]);return 0;}


原创粉丝点击