您的位置:首页 > 其它

BZOJ2435 守卫者的挑战 - 期望dp

2017-08-02 20:42 253 查看
传送门

题解:

考虑dp。dp[i][j][k]表示当前第i场,已经赢了j场,背包容量为k(可能为负)的概率。

转移显然。可以用n+1表示背包容量无穷大(因为显然碎片最多n个,容量太大就变成无穷大了)。

代码:

#include<iostream>
//BZOJ 3029
#include<cstdio>
#include<cstring>
#define MAXN 210
using namespace std;
double dp[2][MAXN][MAXN<<1|1],p[MAXN];
int cnt=0,a[MAXN];
inline int upd(int x) { return x+cnt; }
int main()
{
int n,k,s;scanf("%d%d%d",&n,&s,&k);
for(int i=1;i<=n;i++)
{
int x;scanf("%d",&x);
p[i]=x/100.0;
}
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
if(a[i]==-1) cnt++;
dp[0][0][upd(min(cnt+1,k))]=1.00;
int pre=0,now=1;
for(int i=0;i<n;i++,swap(now,pre))
{
for(int j=0;j<=i+1;j++)
for(int rc=-cnt;rc<=cnt+1;rc++)
dp[now][j][upd(rc)]=0.0;
for(int j=0;j<=i;j++)
4000

for(int rc=-cnt;rc<=cnt+1;rc++)
{
int r=upd(rc);
dp[now][j][r]+=(1-p[i+1])*dp[pre][j][r];
if(a[i+1]==-1)
{
if(r) dp[now][j+1][r-1]+=p[i+1]*dp[pre][j][r];
}
else dp[now][j+1][min(upd(cnt+1),r+a[i+1])]+=p[i+1]*dp[pre][j][r];
}
}
double ans=0.0;swap(now,pre);
for(int i=s;i<=n;i++)
for(int j=0;j<=cnt+1;j++)
ans+=dp[now][i][upd(j)];
printf("%.6lf\n",ans);return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: