zoukankan      html  css  js  c++  java
  • 洛谷 P3239 [HNOI2015]亚瑟王(期望dp)

    题面

    luogu

    题解

    一道复杂的期望(dp)

    思路来源:__stdcall

    容易想到,只要把每张牌打出的概率算出来就可以求出(ans)

    (fp[i])表示把第(i)张牌打出来的概率

    可知:(fp[0] = 1-(1-p[0])^r)
    ((1-p[0])^r)即一直不打出的概率)

    后面的(fp)怎么求?

    (f[i][j])表示前(i)张牌一共出了(j)张的概率, 那么就会有

    (fp[i] = sum_{j=0}^{r}f[i-1][j]*(1-(1-p[i])^{r-j}))
    (1−(1−p[i])^{r−j})就是在(r−j)轮中使用过第(i)张牌的概率)

    那么问题只有如何求(f)

    对于第(i)张牌,只有两种情况:
    1.使用
    (f[i][j] += f[i-1][j-1]*(1-(1-p[i])^{r-j+1}))

    2.不使用
    (f[i][j] += f[i-1][j]*(1-p[i])^{r-j})

    具体看代码。。
    看完题解还是很容易的。。

    Code

    #include<bits/stdc++.h>
    
    #define LL long long
    #define RG register
    
    using namespace std;
    template<class T> inline void read(T &x) {
    	x = 0; RG char c = getchar(); bool f = 0;
    	while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1;
    	while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar();
    	x = f ? -x : x;
    	return ;
    }
    template<class T> inline void write(T x) {
    	if (!x) {putchar(48);return ;}
    	if (x < 0) x = -x, putchar('-');
    	int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10;
    	for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ;
    }
    
    const int N = 230;
    
    double p[N], fp[N], P[N][N], f[N][N];
    int d[N], n, r;
    void pre() {
    	for (int i = 1; i <= n; i++) {
    		P[i][0] = 1;
    		for (int j = 1; j <= r; j++)
    			P[i][j] = P[i][j-1]*(1-p[i]);
    	}
    	return ;
    }
    
    void solve() {
    	read(n); read(r);
    	for (int i = 1; i <= n; i++)
    		scanf("%lf", &p[i]), read(d[i]);
    	pre();
    	memset(f, 0, sizeof(f));
    	memset(fp, 0, sizeof(fp));
    	f[1][0] = P[1][r];
    	f[1][1] = fp[1] = 1-f[1][0];
    	for (int i = 2; i <= n; i++) {
    		for (int j = 0; j <= r; j++) {
    			f[i][j] += f[i-1][j]*P[i][r-j];
    			if (j) f[i][j] += f[i-1][j-1]*(1-P[i][r-j+1]);
    		}
    	}
    	for (int i = 2; i <= n; i++)
    		for (int j = 0; j <= r; j++)
    			fp[i] += f[i-1][j]*(1-P[i][r-j]);
    	double ans = 0;
    	for (int i = 1; i <= n; i++)
    		ans += fp[i]*d[i];
    	printf("%lf
    ", ans);
    	return ;
    }
    
    int main() {
    	int T; read(T);
    	while (T--) solve();
    	return 0;
    }
    
    
  • 相关阅读:
    [javaSE] 看博客学习多线程的创建方式和优劣比较和PHP多线程
    [javaSE] 看知乎学习反射
    [javaSE] 看知乎学习工厂模式
    [android] 新闻客户端主界面部分
    [PHP] 看博客学习观察者模式
    [javascript] 看知乎学习js事件触发过程
    [javascript] 看知乎学习js闭包
    [PHP] 看博客学习插入排序
    [android] ndk环境的搭建
    [android] 看博客学习hashCode()和equals()
  • 原文地址:https://www.cnblogs.com/zzy2005/p/10248844.html
Copyright © 2011-2022 走看看