JZOJ链接
题目很简略,就不说大意了。
很多时候我们会用DP来解决概率问题
由于
1≤n≤20
,因此本题中就明显是状压DP了
参考NOIP2013的青蛙(JZOJ3477)的做法,我们可以发现
对于一个状态
S
,他可能从
可以得到转移方程
Fs=∑Ni=1Fs′∗Pi+(1−∑Pi)∗Fs+1
因为我们有可能得到重复的礼物,于是在推导过程中,会面对一个这样的问题:
那岂不是
Fs
要从自己转移?(因为理论上我们会无限得到重复的礼物)
这是在做青蛙一题时笔者同样想到,纠结了很久的问题。
然而我们可以先不从理论上思考,从方程角度考虑,把转移方程具有
Fs
的项移项,简化:
∑Pi∗Fs=Fs′∗Pi+1
最终把
∑Pi
移向
我们可以得到
Fs=Fs′∗Pi+1∑Pi
时间复杂度
O(2N)
,得以解决此题。
代码
var
f:array[0..1 shl 21] of extended;
p:array[0..20] of extended;
n,i,j,k:longint;
tmp:extended;
s:int64;
begin
readln(n);
s:=0;
for i := 1 to n do
begin
readln(p[i],k);
if p[i]>0 then s:=s+k;
end;
fillchar(f,sizeof(f),0);
for i := 1 to (1 shl n)-1 do
begin
tmp:=0;
for j := 1 to n do
begin
if i and(1 shl (j-1))<>0 then
begin
f[i]:=f[i]+f[i-(1 shl (j-1))]*p[j];
tmp:=tmp+p[j];
end;
end;
f[i]:=(f[i]+1)/tmp;
end;
writeln(s);
writeln(f[(1 shl n)-1]:0:3);
end.