hdu-3366 Passage 概率DP 读懂就能AC hhh

 http://acm.split.hdu.edu.cn/showproblem.php?pid=3366

读题的时候没发现这个P Q 1-P-Q是全集的划分,以为是独立事件,写错了转移方程233

先贪心得排个序,排序规则我们可以通过假设A B/B A这两种顺序,然后推导概率和的大小关系来得出。

然后分别讨论直接通过,免费到下一门,付费到下一门。

dp[i][j]存到达i门消费j的概率,dp[0][0]是初始状态,所以必命中,置为1,其他的概率需要推导得出,所以先置0。

#include <iostream>
#include <string>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <queue>
#define LL long long
using namespace std;
const LL N = 10005,M=15;
int n, m;
double dp[M][N];
struct node
{
    double p, q;
}r[N];
bool cmp(node a, node b)
{
    return a.p*b.q > b.p*a.q;//推导概率公式
}
int main(int argc, const char * argv[]) {
    //cin.sync_with_stdio(false);
    int t;
    //cin >> t;
    int cas = 1;
    scanf("%d", &t);
    while (t--)
    {
        //cin >> n >> m;
        scanf("%d%d", &n, &m);
        for (int i = 0; i < n; i++)
        {
            scanf("%lf%lf", &r[i].p, &r[i].q);
            //cin >> r[i].p >> r[i].q;
        }
        sort(r, r + n, cmp);
        for (int i = 0; i <= m; i++)fill(dp[i], dp[i] + N, 0);
        double ans = 0;
        dp[0][0] = 1;
        for (int i = 0; i <= m; i++)
        {
            for (int j = 0; j < n; j++)
            {
                dp[i][j + 1] += dp[i][j]*(1.0 - r[j].p - r[j].q);
                dp[i + 1][j + 1] +=dp[i][j]*r[j].q;
                dp[i][j] *= r[j].p;
                ans += dp[i][j];
            }
        }
        printf("Case %d: %.5f\n",cas++, ans);
        //cout << ans << endl;
    }
    return 0;
}

 

posted @ 2017-10-08 15:26  Luke_Ye  阅读(417)  评论(0编辑  收藏  举报