小迟最近去参加了一个锦标赛,这个锦标赛总共有n轮比赛,最终成绩由这n轮比赛中赢的轮数决定。至于小迟每一轮比赛的胜利概率,则取决于他在该轮比赛之前的战绩。也就是说,如果小迟在第i轮比赛选择积极应战,并且前i-1轮比赛中取得了j胜的话,那么第i轮比赛的胜利概率为p[i][j],这里我们保证了一点就是对于同一个i,p[i][j]关于j的上升保持单调不上升(也就是说p[i][j]p[i][j+1])。
小迟观察到这个规则之后,想到了一个可能可以使他最终成绩更优的犯法,就是在某些轮比赛采取第二种策略,故意求败,也就是以100%的概率输掉该轮比赛,从而使自己在后面能够遇到更容易对付的对手。
小迟现在已经看到了整个p数组,小迟希望你能告诉他一个最优的策略,使得他能最大化他的期望赢的轮数。这里,定义一下期望。假设我们要求一个事件A的期望,那么假如事件A以Pi的概率结果为i,那么事件A的期望则是i*Pi的和,大概的含义就是结果值关于概率的一个加权平均数。
由于我们看到对于第i轮,无论之前战绩如何,胜率都是相同的,因此我们的最优策略应当是每一轮努力求胜。
然后,第一轮,如果我们赢了,概率为0.5,输了的概率也为0.5。
如果第一轮赢了,第二轮又赢了,概率为0.5*0.5=0.25,赢两盘;
如果第一轮赢了,第二轮输了,概率为0.5*(1-0.5)=0.25,赢一盘;
如果第一轮输了,第二轮赢了,概率为(1-0.5)*0.5=0.25,赢一盘;
如果两轮都输了,概率为(1-0.5)*(1-0.5)=0.25,赢零盘。
故期望赢的轮数为0.25*2+(0.25+0.25)*1+0.25*0=1
对于100%的数据,1≤n≤1000,0≤p[i][j]≤1.

1 /**/
2 #include <cstdio>
3 #include <cstring>
4 #include <cmath>
5 #include <cctype>
6 #include <iostream>
7 #include <algorithm>
8 #include <map>
9 #include <set>
10 #include <vector>
11 #include <string>
12 #include <stack>
13 #include <queue>
14
15 typedef long long LL;
16 typedef unsigned long long ULL;
17 using namespace std;
18 const int maxn = 1000 + 24;
19 int n;
20 double p[maxn][maxn];
21 double dp[maxn][maxn];
22 int main()
23 {
24 scanf("%d",&n);
25 for(int i = 1; i <= n; i++)
26 for(int j = 0; j < i; j++)
27 scanf("%lf", &p[i][j]);
28 dp[0][0] = 1;
29 for(int i = 0; i < n; i++)
30 for(int j = 0; j <= i; j++) {
31 dp[i+1][j+1] += dp[i][j] * p[i+1][j];
32 dp[i+1][j] += dp[i][j] * (1 - p[i+1][j]);
33 }
34 double ans = 0;
35 for(int j = 0; j <= n; j++) ans += j * dp[n][j];
36 printf("%.2lf\n", ans);
37 return 0;
38 }
View Code
由大佬的博客可知,放水是题目中设置的干扰。于是蒟蒻不管它,直接写了。
状态转移方程好像也挺好理解的
第一次在博客园写随笔,好像紧张得写不出话来....就这样吧