日常刷题2025-3-22
日常刷题2025-3-22
E - Expansion Packs
蓝色
评述:期望DP+概率DP
一道非常棒的DP题目,非常推荐。典型的自以为做不了实际上思考上的困难在实现过程中都没遇到。
代码
#include<bits/stdc++.h>
using namespace std;
int n,X,p[5002];
double f[5002],g[5002],h[5002][5002],P[5002];
int main(){
scanf("%d%d",&n,&X);
for(int i=1;i<=n;++i)scanf("%d",&p[i]),P[i]=1.0*p[i]/100;
//f[i] 表示一包卡恰好抽出 i 张 rare card(s) 的概率
//h[i][j] 表示一包卡的前 i 张卡抽出 j 张 rare card(s) 的概率
h[0][0]=1;
for(int i=0;i<n;++i)
for(int j=0;j<=n;++j){
h[i+1][j]+=h[i][j]*(1-P[i+1]);
h[i+1][j+1]+=h[i][j]*P[i+1];
}
for(int i=0;i<=n;++i)f[i]=h[n][i];
//空间复杂度 O(n^2),因为需要 h,但可以优化到 n(类似滚动数组,但更简单)
//DP 类似背包。
//g[i]:抽出至少i张稀有卡期望抽g[i]包。
//g[0]=0
for(int i=1;i<=X;++i){
double sum=0,alpha=0;
for(int j=0;j<=n;++j){
if(j>=i)continue;
if(j==0)alpha=f[j];
else sum+=f[j]*g[i-j];
}
sum+=1;
g[i]=sum/(1-alpha);
}
printf("%.10lf",g[X]);
}