分析:
和这道题还是蛮像的
但是抽到每张卡片的概率不同了
注意:And it is possible that there is nothing in the bag.
状态压缩,处理方式和poj2096
我们还是要倒着退:
f[(1<<n)−1]=0
f
[
(
1
<<
n
)
−
1
]
=
0
f[i]
f
[
i
]
表示拥有状态
i
i
的卡片的期望,设为空包的概率
枚举下一包中的卡片
j
j
(状态中没有
j
j
)
(
i
i
中没有)
f[i]−>f[i]∗p[k]
f
[
i
]
−
>
f
[
i
]
∗
p
[
k
]
(
i
i
中有)
f[i]−>f[i]∗x
f
[
i
]
−
>
f
[
i
]
∗
x
f[i]=(f[i]+1)∗x+∑(f[i]+1)∗p[k]+∑(f[i|(1<<j)]+1)∗p[j] f [ i ] = ( f [ i ] + 1 ) ∗ x + ∑ ( f [ i ] + 1 ) ∗ p [ k ] + ∑ ( f [ i | ( 1 << j ) ] + 1 ) ∗ p [ j ]
f[i]=x+∑(f[i|(1<<j)]+1)∗p[j]1−(x+∑p[k]) f [ i ] = x + ∑ ( f [ i | ( 1 << j ) ] + 1 ) ∗ p [ j ] 1 − ( x + ∑ p [ k ] )
tip
倒退的思路还是很巧妙的
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=1500000;
int n;
double p[21],f[N],x;
int main()
{
while (scanf("%d",&n)!=EOF) {
x=1.0;
for (int i=0;i<n;i++) scanf("%lf",&p[i]),x-=p[i];
memset(f,0,sizeof(f));
for (int i=(1<<n)-2;i>=0;i--) {
double t=0;
double sum=x;
for (int j=0;j<n;j++)
if (!(i>>j&1)) //没有这种卡片
t+=(f[i|(1<<j)]+1.0)*p[j];
else sum+=p[j];
t+=sum;
f[i]=t/(1-sum);
}
printf("%0.4lf\n",f[0]);
}
return 0;
}