tyvj 1864 守卫者的挑战

传送门

解题思路

dp[i][j][k]表示前i个挑战,赢了j场,现在还有k个包的获胜概率。
转移方程:
dp[i+1][j+1][k+a[i]] += p[i+1]*dp[i][j][k] (k+a[i]>=0)
dp[i+1][j][k]+=(1-p[i+1])*dp[i][j][k]
时间复杂度O(n^3)

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
const int MAXN = 205;

inline int rd(){
  int x=0,f=1;char ch=getchar();
  while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
  while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
  return x*f;
}

int n,k,L;
double dp[MAXN][MAXN][MAXN],ans;

struct Bag{
    double p;
    int a;
}bag[MAXN];

inline bool cmp(Bag x,Bag y){
    return x.a>y.a;
}

int main(){
  n=rd();L=rd();k=rd();
  for(register int i=1;i<=n;i++) {
    int x=rd();
    bag[i].p=(double)x/100;
  }
  for(register int i=1;i<=n;i++) bag[i].a=rd();
  sort(bag+1,bag+1+n,cmp);
  dp[0][0][k]=1;
  for(register int i=0;i<n;i++)
    for(register int j=0;j<=i;j++)
      for(register int o=n;o>=0;o--){
        dp[i+1][j][o]+=dp[i][j][o]*(1-bag[i+1].p);
        if(o+bag[i+1].a<0) continue;
        dp[i+1][j+1][min(o+bag[i+1].a,n)]+=dp[i][j][o]*bag[i+1].p;
   }
    for(register int i=0;i<=n;i++)
      for(register int j=L;j<=n;j++)
        ans+=dp[n][j][i];
    printf("%.6lf",ans);
  return 0;
}
posted @ 2018-07-22 17:01  Monster_Qi  阅读(131)  评论(0编辑  收藏  举报