BZOJ 4008 (期望,动态规划)

BZOJ 4008 (期望,动态规划)

曾经见过zzzzx做过这道题,他被精度问题卡了,没想到我做到了这道题,物是人非啊。
这道期望DP挺难做。
原因是状态的设计非常匪夷所思。

Orz stdcall
考虑每一回合的期望,但是由于题目的种种限制,只可以使用状压来解决问题。
我们考虑改变状态。
不妨计算出每张卡牌的概率。
那么我们设\(f[i]\)表示\(i\)这张卡牌的概率。
考虑如何推导f[i]
\(dp[i][j]\)表示在所有的\(r\)轮中,前\(i\)张卡中一共出了\(j\)张的概率。
\(f[i]\)的转移
\[f[i] = \sum_{j > 0}dp[i - 1][j] * [1 - (1 -p[i])^{r - j}]\]
\(dp[i][j]\)的转移
\[dp[i][j] = \]
\[dp[i - 1][j] * [1 - (1 - p[i])^{r - j}] \]
\[ + \]
\[[j > 0]dp[i - 1][j - 1] * [1 - (1-p[i])^{r - j + 1}]\]
预处理\((1 - p[i])\)的值即可.

DP细节好多啊,发现拆成函数这样比较好调

/*header*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <map>
#include <queue>
#define gc getchar()
#define pc putchar
#define ll long long
#define mk make_pair
#define fi first
#define se second
using std::min;
using std::max;
using std::swap;
const int maxN = 220 + 7;
const double oe = 1.00000000000000;

inline int gi() {
  int x = 0,f = 1;char c = gc;
  while(c < '0' || c > '9') {if(c == '-')f = -1;c = gc;}
  while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = gc;}return x * f;
}

double a[maxN][maxN] , b[maxN][maxN];
double dp[maxN][maxN] , f[maxN];
double p[maxN];
int d[maxN] , n, r;

void Pre() {
    for(int i = 1;i <= n;++ i)  {
        b[i][0] = oe;
        for(int j = 1;j <= r;++ j) 
            b[i][j] = b[i][j - 1] * (oe - p[i]);    
    }
    return;
}

void Solve() {
    dp[1][0] = b[1][r];
    f[1] = dp[1][1] = 1- dp[1][0];
    for(int i = 2;i <= n;++ i) {
        for(int j = 0;j <= r;++ j) {
            f[i] += dp[i - 1][j] * (oe - b[i][r - j]);
            dp[i][j] += dp[i - 1][j] * b[i][r - j];
            if( j )  dp[i][j] += dp[i - 1][j - 1] * (oe - b[i][r - j + 1]);
        }
    }
    double ans = 0; 
    for(int i = 1;i <= n;++ i) ans += f[i] * d[i];
    printf("%.10lf\n",ans);
}

int main() {
    int T = gi();
    while(T --) {
        memset(f , 0, sizeof(f));
        memset(dp , 0, sizeof(dp));
        n = gi() , r = gi();
        for(int i = 1;i <= n;++ i)  scanf("%lf%d",&p[i] , &d[i]);
        Pre();
        Solve();
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/gzygzy/p/10364220.html