codeforces---167BWizards and Huge Prize 概率DP

题目链接:https://codeforces.com/problemset/problem/167/B

题目大意:有n场比赛,你至少要赢l次才算优秀,你有一个大小为k的包,每场比赛的胜率为$p_i$,每场比赛赢得的奖品为$a_i$如果$a_i<0$则是奖品,否则就是一个容量为$a[i]$的背包。问你在优秀的时候拿走所以赢得奖品的概率。

Examples

Input
3 1 0
10 20 30
-1 -1 2
Output
0.300000000000
Input
1 1 1
100
123
Output
1.000000000000

DP。。。真的有点无力。。。。

设置状态为$dp[i][j][k]$,表示为前$i$场比赛赢得$j$场后的背包剩余空间$k$。由于比赛的顺序是无序的,那么我们可以对初始状态背包容量+200(因为最多200个奖品),那么这样就可以随便拿了,最后确定状态的时候小于200的就直接舍弃了。

以下是AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int mac=210;

int a[mac];
double p[mac];
double dp[mac][mac][2*mac];

int main()
{
    int n,l,v;
    scanf ("%d%d%d",&n,&l,&v);
    for (int i=1; i<=n; i++)
        scanf ("%lf",&p[i]),p[i]/=100;
    for (int i=1; i<=n; i++)
        scanf ("%d",&a[i]);
    dp[0][0][v+200]=1;
    for (int i=0; i<n; i++)
        for (int j=0; j<=i; j++)
            for (int k=0; k<=400; k++){//枚举空间
                int last=min(k+a[i+1],400);
                dp[i+1][j][k]+=dp[i][j][k]*(1-p[i+1]);//本场失败
                if (last>0)
                    dp[i+1][j+1][last]+=dp[i][j][k]*p[i+1];
            }
    double ans=0;
    for (int i=200; i<=400; i++)
        for (int j=l; j<=n; j++)
            ans+=dp[n][j][i];
    printf("%.10f\n",ans);
    return 0;
}

 

posted @ 2020-07-04 15:13  lonely_wind  阅读(202)  评论(0编辑  收藏  举报