2019.7.16
hzoi noip模拟T1
发现自己就是个**,一看到概率DP就犯难。硬着头皮打暴力,连精度也不会卡,尽管知道概率DP都倒着推,emmm。。。
首先,要明确题面,是有P[i]的几率买到此礼物,而一次只买到一件。然后,显然,P[i]>0,所以最大喜悦值为sum
10%
print 1/P[1]
100%
n<=20 考虑状压,dp[state]表示从dp[(1<<N)-1]到此的期望,初始状态为dp[(1<<N)-1]=0 。
有转移式
dp[state]=Σ{(dp[state]+1)*P[s+1]}(买到已买到的)+(dp[state]+1)*(1-ΣP[i])(啥都没买到)+Σ{(dp[state^(1<<s)]+1)*P[s+1]}
然后移项即可


#include<cstdio> #include<iostream> #define MAXN 25 using namespace std; int W[MAXN]; double P[MAXN]; int N; double mei=1.0; double dp[(1<<20)+1]; long long sum; int main(){ // freopen("da.in","r",stdin); scanf("%d",&N); for(int i=1;i<=N;++i){ scanf("%lf%d",&P[i],&W[i]); mei-=P[i]; sum+=W[i]; } int lim=(1<<N)-1; dp[0]=0; double lin,xi; for(int state=lim-1;state>=0;--state){ // printf("orz state=%d\n",state); xi=1.0; for(int s=0;s<N;++s) if(!((1<<s)&state)) dp[state]+=(dp[state^(1<<s)]+1)*P[s+1]; else{ xi-=P[s+1]; dp[state]+=P[s+1]; } dp[state]+=mei; dp[state]/=(xi-=mei); // printf("xi=%lf\ndp[%d]=%lf\n",xi,state,dp[state]); } printf("%lld\n%.3lf\n",sum,dp[0]); }
别忘了W[i]<=10^9
开long long