【JZOJ4685】礼物

JZOJ链接
题目很简略,就不说大意了。
很多时候我们会用DP来解决概率问题
由于 1n20 ,因此本题中就明显是状压DP了
参考NOIP2013的青蛙(JZOJ3477)的做法,我们可以发现
对于一个状态 S ,他可能从S加上任何一个礼物(也可能没有礼物)从而得到
可以得到转移方程 Fs=Ni=1FsPi+(1Pi)Fs+1
因为我们有可能得到重复的礼物,于是在推导过程中,会面对一个这样的问题:
那岂不是 Fs 要从自己转移?(因为理论上我们会无限得到重复的礼物)
这是在做青蛙一题时笔者同样想到,纠结了很久的问题。
然而我们可以先不从理论上思考,从方程角度考虑,把转移方程具有 Fs 的项移项,简化:
PiFs=FsPi+1
最终把 Pi 移向
我们可以得到 Fs=FsPi+1Pi
时间复杂度 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.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值