BZOJ2784[JLOI2012]时间流逝
Posted G . H . O . S . T . R . E . A
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ2784[JLOI2012]时间流逝相关的知识,希望对你有一定的参考价值。
Description
Input
Output
Sample Input
1
0.5 1 2
1 2
Sample Output
2.000
HINT
对于所有数据,0.1≤P≤0.9,1≤T≤50,1≤N≤30。
题解:
概率DP题,我想了好久以后开始写,调了好几个小时都没有写对。
直到我看了czt的代码,我在发现我原本推出的状态转移方式是错误的。
正确的DP方式:
用[i,j]记录已经筹集了i的能量,且拥有的最小能量圈为j,让其发展下去,直到筹集t以上的能量或失去j能量圈为止的情况。
用f[i,j,1]记录有多大的几率在能量满之前会失去j能量圈,用f[i,j,2]记录能量满或失去j的期望天数。
初始状态:f[i,j,1]=0,f[i,j,2]=0。(i>=t) 假设[i,j]时获得了一个k的能量圈(k<=j),则f[i,j]可以通过f[i+k,k]转移而来。
设x[k]为当前获得k的概率。
原地踏步(即获得k后进入[i+k,k]状态却失去k)的概率p1为∑(f[i+k,k,1]*x[k])。
没有原地踏步的概率p2为1-p1。
从[i,j]开始,直到第一次因为失去k而回到[i,j]或者能量满的 概率*期望步数 之和tot为∑((f[i+k,k,2]+1)*x[k])。
推一推公式,可得f[i,j,1]=p/p2,f[i,j,2]=(tot/p2)+f[i,j,1]*1。
对于没有能量圈的状态(即答案),不会遇到鱼,转移方式与上面的略有不同,但大致是一样的。
代码:
1 var 2 i,j,k,l,n,m,t:longint; 3 p1,p2:extended; 4 b:array[0..1000,0..100,1..2]of extended; 5 lb,qz:array[0..100]of longint; 6 ans:extended; 7 begin 8 while not eof do 9 begin 10 fillchar(lb,sizeof(lb),0); 11 fillchar(qz,sizeof(qz),0); 12 fillchar(b,sizeof(b),0); 13 readln(p1,t,n); inc(t); p1:=1-p1; 14 for i:=1 to n do begin read(j); inc(lb[j]); end; readln; 15 for i:=1 to 100 do qz[i]:=qz[i-1]+lb[i]; 16 for i:=t-1 downto 1 do 17 for j:=1 to 100 do 18 if lb[j]>0 then 19 begin 20 p2:=1; 21 for k:=1 to j do 22 if lb[k]>0 then 23 begin 24 if i+k<t then 25 begin 26 p2:=p2-p1*(lb[k]/qz[j])*b[i+k,k,1]; 27 b[i,j,2]:=b[i,j,2]+p1*(lb[k]/qz[j])*(1+b[i+k,k,2]); 28 end else b[i,j,2]:=b[i,j,2]+p1*(lb[k]/qz[j]); 29 end; 30 b[i,j,1]:=(1-p1)/p2; b[i,j,2]:=b[i,j,2]/p2; 31 b[i,j,2]:=b[i,j,2]+b[i,j,1]; 32 end; 33 p2:=1; ans:=0; 34 for k:=1 to 100 do 35 if lb[k]>0 then 36 begin 37 if k<t then 38 begin 39 p2:=p2-(lb[k]/n)*b[k,k,1]; 40 ans:=ans+(lb[k]/n)*(1+b[k,k,2]); 41 end else ans:=ans+lb[k]/n; 42 end; 43 writeln((ans/p2):0:3); 44 end; 45 end.
以上是关于BZOJ2784[JLOI2012]时间流逝的主要内容,如果未能解决你的问题,请参考以下文章