BZOJ 3029 守卫者的挑战

Posted on 2017-03-15 21:36  ziliuziliu  阅读(198)  评论(0编辑  收藏  举报

一开始搞了两个dp数组,分别记到第i盘,胜j盘,拿到k个碎片和背包大小>=k的概率,然后寻思着把它们乘起来?

后来发现好像是错的。。。。这个地方不能用乘法,这两件事情是相关的。(我瞎jb猜的。。。其实是样例没过)

然后发现只要一个数组就行了。。。。收益就是+a[i],-1,问最后收益>=0,胜场>=l的方案数。。。然后直接dp。

卡内存差评。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 201
using namespace std;
int n,x,l,k,a[maxn];
double p[maxn],dp[maxn][maxn][maxn<<1],ans=0;
int main()
{
    scanf("%d%d%d",&n,&l,&k);
    for (int i=1;i<=n;i++) {scanf("%d",&x);p[i]=x/100.0;}
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    dp[0][0][k+200]=1.0;
    for (int i=0;i<n;i++)
        for (int j=0;j<=n;j++)
            for (int k=-n;k<=n;k++)
            {
                dp[i+1][j][k+200]+=dp[i][j][k+200]*(1-p[i+1]);
                int base=k+a[i+1]+200;base=min(base,n+200);base=max(base,-n+200);
                dp[i+1][j+1][base]+=dp[i][j][k+200]*p[i+1];
            }
    for (int i=l;i<=n;i++)
        for (int k=0;k<=n;k++)
            ans+=dp[n][i][k+200];
    printf("%.6lf\n",ans);
    return 0;
}