bzoj4008: [HNOI2015]亞瑟王【指望dp】

  一個特別神奇的dp,特別厲害。c++

  f(i, j) 表示 有 j 輪發動技能的牌在 [1, i] 另外的m - j輪在[i + 1, n]之間的機率。
ide

  怎麼轉移呢?spa

  首先考慮i這張牌不選的狀況,f(i - 1, j) 表示 j --> [1, i - 1] && m - j --> [i, n]        (用箭頭表示在[]之間...),那麼咱們只須要讓在[i, n]之間的m - j個選擇都不是i便可,那麼咱們應該 * (1 - p[i]) ^ (m - j)
code

  再考慮這張牌咱們要選的狀況,f(i - 1, j - 1)表示 j - 1 --> [1, i - 1] && m - j + 1 --> [i, n], 那麼咱們須要m - j + 1中至少有一個i, 因此咱們應該 * (1 - (1 - p[i]) ^ (m - j + 1))
blog

  因此就有了轉移方程:it

$\mbox{f(i, j) = f(i - 1, j) * (1 - p[i]) ^ {m - j} + f(i - 1, j - 1) * (1 - (1 - p[i]) ^ {m - j + 1})}$event

  那麼初始條件是多少呢? f(0, 0) == 1 爲何呢:class

  m次選擇都在n之間的機率爲1,那麼f(n, m) == 1,這意味着m --> [1, n] 那麼 另外的 0個選擇--> 0,因此f(0, 0) == 1.cli

 

  那麼答案是多少呢?sed

  應該是對於每個撲克牌,咱們掃描整個m輪,用當前的機率與撲克牌的貢獻的成績累加答案。

  ans += d[i] * f[i - 1][j] * (1 - pow(1 - p[i], m - j)); 用j --> [1, i - 1] && m - j --> [i, n] 而且m - j中至少有一個i。

 1 #include <bits/stdc++.h>
 2 #define rep(i, a, b) for (int i = a; i <= b; i++)
 3 #define drep(i, a, b) for (int i = a; i >= b; i--)
 4 #define REP(i, a, b) for (int i = a; i < b; i++)
 5 #define mp make_pair
 6 #define pb push_back
 7 #define clr(x) memset(x, 0, sizeof(x))
 8 #define xx first
 9 #define yy second
10 using namespace std;
11 typedef long long i64;
12 typedef pair<int, int> pii;
13 const int inf = ~0U >> 1;
14 const i64 INF = ~0ULL >> 1;
15 //***********************************
16 
17 long double p[225]; int d[225];
18 long double f[225][135];
19 
20 int main() {
21     int T; scanf("%d", &T);
22     while (T--) {
23         int n, m;
24         scanf("%d%d", &n, &m);
25         rep(i, 1, n) scanf("%Lf%d", &p[i], &d[i]);
26         memset(f, 0, sizeof(f));
27         f[0][0] = 1;
28         rep(i, 1, n) {
29             rep(j, 0, m) f[i][j] = f[i - 1][j] * pow(1 - p[i], m - j) + f[i - 1][j - 1] * (1 - pow(1 - p[i], m - j + 1));
30         }
31         long double ans(0);
32         rep(i, 1, n) {
33             rep(j, 0, m) {
34                 ans += d[i] * f[i - 1][j] * (1 - pow(1 - p[i], m - j));
35             }
36         }
37         printf("%.10Lf\n", ans);
38     }
39     return 0;
40 }
View Code

 

 

  有一點還不太理解,就是在轉移的時候,假如咱們選取了i,那麼用f(i - 1, j - 1)轉移的時候乘的是至少有一個i的機率,那假如大於1個那麼和題意不就矛盾了嗎。。求助。。。

相關文章
相關標籤/搜索