您的位置:首页 > 其它

51nod 1450 闯关游戏 期望dp

2017-10-27 16:55 197 查看

题意

一个游戏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内)

1<=N<=2000,N <= M <= 2N

分析

发现自己期望方面菜的抠脚。。。搞了一天才略微搞懂这道题目。

显然是把所有人按照Y从小到大排序,当做到一个位置i,满足剩下的游戏全都要两星才能通关时,就需要不停地做这些游戏直到两星。

设f[i,j]表示前i个游戏抽到j颗星的概率,转移十分显然。

然后直接统计答案即可。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=2005;

int n,m;
pair<int,int> a
;
double f
[N*2],s1
,s2
;

int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
a[i]=make_pair(y,x);
}
sort(a+1,a+n+1);
for (int i=1;i<=n;i++)
{
double x=(double)a[i].second/1000,y=(double)a[i].first/1000;
double p1=1/(x+y),p2=1/y;
s1[i]=s1[i-1]+p1;s2[i]=s2[i-1]+p2;
}
if (n*2<=m)
{
printf("%.10lf\n",s2
);
return 0;
}
f[0][0]=1;
double ans=0;
for (int i=1;i<=n;i++)
{
double x=(double)a[i].second/1000,y=(double)a[i].first/1000;
double p1=x/(x+y),p2=1-p1,p=s1[i]+s2
-s2[i];
for (int j=i;j<=n*2;j++)
{
f[i][j]=f[i-1][j-1]*p1;
if (j>1) f[i][j]+=f[i-1][j-2]*p2;
if ((n-i)*2==m-j) ans+=p*f[i][j];
if ((n-i)*2<=m-j) f[i][j]=0;
}
}
for (int i=m+1;i<=n*2;i++) ans+=s1
*f
[i];
printf("%.10lf",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: