Codeforces 167B Wizards and Huge Prize(概率dp)

题意:

n个人,开始有一个容量为k得背包,击败一个人背包可以获得一定容量或得到一个财富(放入背包内),给出击败每个人的概率,求至少击败l个人,且背包容量大于获得的总财富值的概率

分析:

状态好确定,dp[i][j][k]表示前i个人击败j个背包容量是k是的概率,求概率正推,要注意这时背包容量能为负,我们把容量都加上B。

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <string>
#include <cctype>
#include <complex>
#include <cassert>
#include <utility>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
#define lson l,m,rt<<1
#define pi acos(-1.0)
#define rson m+1,r,rt<<11
#define All 1,N,1
#define read freopen("in.txt", "r", stdin)
#define B 201
const ll  INFll = 0x3f3f3f3f3f3f3f3fLL;
const int INF= 0x7ffffff;
const int mod =  1000000007;
double dp[210][210][2*B+10];
int a[210],p[210];
int n,l,k;
void solve(){
    memset(dp,0,sizeof(dp));
    dp[0][0][B+k]=1;
    for(int i=1;i<=n;++i)
        for(int j=0;j<=i;++j)
        for(int k=0;k<=2*B;++k)
        {
            dp[i][j][k]+=dp[i-1][j][k]*(1-p[i]/100.0);//未击败第i个人
            if(a[i]==-1){
                if(k>0)//必须能放下一个财富
                dp[i][j+1][k-1]+=dp[i-1][j][k]*(p[i]/100.0);
            }
            else{
            if(k+a[i]>2*B)
            dp[i][j+1][2*B]+=dp[i-1][j][k]*(p[i]/100.0);
            else
            dp[i][j+1][k+a[i]]+=dp[i-1][j][k]*(p[i]/100.0);
            }
        }
    //符合条件的情况的概率和
double total=0.0; for(int j=l;j<=n;++j) for(int k=B;k<=2*B;++k) total+=dp[n][j][k]; printf("%.12lf\n",total); } int main() { while(~scanf("%d%d%d",&n,&l,&k)){ for(int i=1;i<=n;++i) scanf("%d",&p[i]); for(int i=1;i<=n;++i) scanf("%d",&a[i]); solve(); } return 0; }

 

posted on 2015-09-01 22:28  积跬步、至千里  阅读(292)  评论(0编辑  收藏  举报

导航