概率DP

1. Wannafly挑战赛3- A  珂朵莉

  题面:给你一个长 n 的序列,m 次查询 。每次查询给一个 x,然后: 从序列的最左端 1 开始,每次随机的选择一个右端点 r,如果两个端点间的区间和不超过 x ,就进行一次分割,然后把左端点变成 r + 1, 否则一直随机下去。 问这样分割出来的期望段数

  思路:dp[i]表示[i,n]的期望段数,Sum[i]表示[i,n]区间dp和。假设R为i为起点时满足条件的最右端,区间[i,R]内处处等可能分割,分割点为k时,[i,k]为1段,后面分割的期望为dp[k+1],所以总期望dp[k+1]+1,而分割点可取[i,R],故:dp[i]=sum{dp[t+1]+1|i<=t<=R}/(R-i+1)。

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 const int maxn = 100010;
 5 int n, m;
 6 int A[maxn];
 7 double dp[maxn],Sum[maxn];//dp[i]表示[i,n]的期望段数
 8 //Sum[i]表示[i,n]区间dp和
 9 
10 int main()
11 {
12     scanf("%d%d", &n, &m);
13     int maxnum = -1;
14     for (int i = 1; i <= n; i++) scanf("%d", A + i),maxnum=max(maxnum,A[i]);
15     while (m--)
16     {
17         int x;
18         scanf("%d", &x);
19         if (x < maxnum) printf("cumt acm up up!\n");
20         else
21         {
22             dp[n] = Sum[n] = 1;
23             Sum[n+2]=Sum[n + 1] = 0.0;//设置边界,方便后边(Sum[i+1]-Sum[R+1])
24             int tmp = 0,R=n;
25             for (int i = n; i >= 1; i--)
26             {
27                 tmp += A[i];
28                 if (tmp > x)
29                 {
30                     while (tmp > x) tmp -= A[R--];
31                 }
32                 //区间[i,R]内处处等可能分割,分割点为k时,[i,k]为1段,后面分割的期望为dp[k+1],所以总期望dp[k+1]+1,而分割点可取[i,R],故:
33                 //dp[i]=sum{dp[t+1]+1|i<=t<=R}/(R-i+1)
34                 dp[i] = 1.0 + (Sum[i + 1] - Sum[R + 2]) / (1.0*R - i + 1);
35                 Sum[i] = Sum[i + 1] + dp[i];
36             }
37             printf("%.2lf\n", dp[1]);
38         }
39     }
40     return 0;
41 }
View Code

 

posted @ 2018-03-11 08:57  萌萌的美男子  阅读(173)  评论(0编辑  收藏  举报