题目描述
夏川的生日就要到了。作为夏川形式上的男朋友,季堂打算给夏川买一些生 日礼物。
商店里一共有种礼物。夏川每得到一种礼物,就会获得相应喜悦值Wi(每种 礼物的喜悦值不能重复获得)。
每次,店员会按照一定的概率Pi(或者不拿出礼物),将第i种礼物拿出来。 季堂每次都会将店员拿出来的礼物买下来。没有拿出来视为什么都没有买到,也 算一次购买。
众所周知,白毛切开都是黑的。所以季堂希望最后夏川的喜悦值尽可能地高。
求夏川最后最大的喜悦值是多少,并求出使夏川得到这个喜悦值,季堂的期 望购买次数。
输入
第一行,一个整数N,表示有N种礼物。
接下来N行,每行一个实数Pi和正整数Wi,表示第i种礼物被拿出来的概率和 可以获得喜悦值。
输出
第一行,一个整数表示可以获得的最大喜悦值。
第二行,一个实数表示获得这个喜悦值的期望购买次数,保留3位小数。
样例输入
3
0.1 2
0.2 5
0.3 7
样例输出
14
12.167
提示
对于10%的数据,N = 1
对于30%的数据,N ≤ 5
对于100%的数据,N ≤ 20 ,0 < Wi ≤ 10^9 ,0 < Pi ≤ 1且∑Pi ≤ 1
注意:本题不设spj
已经废物到这种水题都做不来了
主要是考场上没给这题时间
这种期望dp还是应该倒着推 因为最终状态比较显然
设$dp[i]$为物品购入状态为$i$时买到所有商品的期望步数
那么有:
$dp[i]=\sum \limits _{k=1}^{n} {p[k]*dp[j]}+(1-\sum \limits{p[k]})*dp[i]+1$
+号前是多买一件的状态j转移到i,+号后是非酋没抽到卡回到i状态的转移
移项化简可得$dp[i]=\frac{\sum{p[k]*f[j]}+1}{\sum{p[k]}}$
目标:$dp[0]$
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> using namespace std; typedef long long ll; const int N=23; const double eps=1e-8; int n,val[N],side; double P[N],sum,f[(1<<20)+5]; ll ans1=0; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%lf%d",&P[i],&val[i]); if(P[i]>eps)ans1+=val[i]; } cout<<ans1<<endl; int side=(1<<n)-1; f[side]=0; for(int i=side-1;i>=0;i--) { double sump=0; for(int j=1;j<=n;j++) { if((i&(1<<(j-1)))==0) { f[i]+=P[j]*f[i|(1<<(j-1))]; sump+=P[j]; } } f[i]++; //cout<<f[i]<<endl; f[i]/=sump; } printf("%.3lf\n",f[0]); return 0; }
(似乎有发糖倾向的题面都和我八字不合?)