题意:n个人,玩抓人游戏,每抓住一个人都要猜这个人是谁。对于每一局,第i个人有$p_{i}$的概率被抓到。游戏结束当且仅当每个人都在某局中被抓到并且猜中自己的名字,求一个合适的策略来使得期望游戏局数最少,输出这个期望最少局数.
题解:设$g[i]$表示到$i$局为止,已经全部被猜中过的概率,$f[i][x]$表示到第$i$局为止,已经猜中过第$x$个人的概率。
那么有$$ans = \sum_{i = 1}^{\infty} (g[i] - g[i - 1])i$$
随游戏局数增长,$g[x]$会趋近于1,要让期望最小,显然在$x$越小时,要让$g[x] - g[x - 1]$越大越好,即$g[x]$增长的越快越好。
若在第$i$局猜被抓到的是$k$,那么有:
$f[i][x] = \begin{cases}
f[i - 1][x] + (1 - f[i - 1][x]) p_{x} \quad x == k\\
f[i - 1][x] \quad x != k
\end{cases}$
$g[x] = g[x - 1] \frac{f[x][k]}{f[x - 1][k]}($因为只有$f[x][k]$变化了)
因此我们只需要让$\frac{f[x][k]}{f[x - 1][k]}$最大即可。
$$\frac{f[x][k]}{f[x - 1][k]} = \frac{f[x - 1][k] + (1 - f[x - 1][k])p_{k}}{f[x - 1][k]} = 1 + \frac{(1 - f[x - 1][k])p_{k}}{f[x - 1][k]}$$
所以要使$\frac{(1 - f[x - 1][k])p_{k}}{f[x - 1][k]}$最大。
因此我们枚举$k$,贪心的找最优策略并更新答案,大约$3e5$次可以满足精度要求

这里注意为了满足初始化的要求(在没有把n个人都猜过之前,是没有概率全部猜中的),所以要在最开始先把n个人都猜一遍,然后再继续贪心

 #include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 110
#define ld double int n;
ld ans, last, g;
ld f[AC], p[AC]; inline int read()
{
int x = ;char c = getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x;
} ld cal(int x){
return f[x] + 1.0 * ( - f[x]) * p[x];
} void pre()
{
n = read(), last = ;
for(R i = ; i <= n; i ++)
f[i] = p[i] = 1.0 * read() / 100.0, last *= p[i];//根据转移式来的
ans = n * last;//因为只有猜过所有人之后才有可能结束游戏。。。
} /* int x = 0; ld maxn = 0;
for(R j = 1; j <= n; j ++)
{
ld now = cal(j);
if(cal(j) / f[j] > maxn) maxn = now, x = j;
} */
void work()//为了解决初始化问题,,,先把所有人都猜一遍
{
for(R i = n + ; i <= ; i ++)
{
int x = ; //x不能默认为1,不然f[x]就为0了,,,,
for(R j = ; j <= n; j ++)
if(cal(j) / f[j] > cal(x) / f[x]) x = j;
g = last * cal(x) / f[x], f[x] = cal(x);
ans += i * (g - last), last = g;
}
printf("%.10lf\n", ans);
} int main()
{
freopen("in.in", "r", stdin);
pre();
work();
fclose(stdin);
return ;
}

最新文章

  1. dedecms调用标签总结(一)
  2. Java中List、Set和Map的区别--转载
  3. iOS人机界面指南(翻译)
  4. Spring MVC Junit4 单元測试 JunitTest
  5. Poj 3982 序列
  6. convert 时间转换
  7. 解决编译时出错提示: &#39;error: array must be initialized with a brace-enclosed initializer&#39; 的错误
  8. Postman----安装Newman
  9. c++析构函数调用时机
  10. c#常用数值范围汇总
  11. 洛谷 P1102 A−B数对
  12. Spark SQL访问PostgreSQL
  13. poj3087 Shuffle&#39;m Up(模拟)
  14. svelte 构建快速web 应用的工具
  15. 基础练习 回形取数 (循环 + Java 输入输出外挂)
  16. Java并发编程 - 基本概念
  17. alias别名使用
  18. C 指针改变变量值
  19. Jackson2.1.4 序列化对象时,过滤null的属性 empty的属性 default的属性
  20. Python学习---面向对象的学习[深入]

热门文章

  1. Drupal views中实现两列布局
  2. replace与replaceAll的区别
  3. 五、Django之路由系统
  4. python全栈开发-前方高能-生成器和生成器表达式
  5. 软考之信息安全工程师(包含2016-2018历年真题详解+官方指定教程+VIP视频教程)
  6. Swoole实现h5版聊天室笔记
  7. Jenkins单元测试
  8. POJ-3122(二分算法)
  9. Keepalived两节点出现双VIP的情况
  10. 根据Unicode码生成汉字