1. 程式人生 > >【BZOJ 4832】 [Lydsy2017年4月月賽] 抵制克蘇恩 期望概率dp

【BZOJ 4832】 [Lydsy2017年4月月賽] 抵制克蘇恩 期望概率dp

line bzoj fin etc ring sum pre mes lin

打記錄的題打多了,忘了用開維記錄信息了......我們用f[i][j][l][k]表示已經完成了i次攻擊,隨從3血剩j個,2血剩l個,1血剩k個,這樣我們求出每個狀態的概率,從而求出他們對答案的貢獻並加和,一開始我用的期望忘了轉移的時候不能用1而要用概率......

#include <cstdio>
#include <cstring>
#define r register
using namespace std;
typedef long double LD;
inline int read()
{
    r int sum=0;
    r char ch=getchar();
    
while(ch<0||ch>9)ch=getchar(); while(ch>=0&&ch<=9) { sum=(sum<<1)+(sum<<3)+ch-0; ch=getchar(); } return sum; } LD f[55][10][10][10]; int main() { r int T=read(); while(T--) { for(r int i=0;i<55;++i) for(r int j=0;j<10
;++j) for(r int l=0;l<10;++l) for(r int k=0;k<10;++k) f[i][j][l][k]=0.0; r int K=read(),A=read(),B=read(),C=read(); f[0][C][B][A]=1.0; LD ans=0.0; for(r int i=0;i<K;++i) for(r int j=0;j<=7;++j) for(r int l=0;l+j<=7
;++l) for(r int k=0;k+j+l<=7;++k) { f[i+1][j][l][k]+=f[i][j][l][k]/(1+j+l+k); ans+=f[i][j][l][k]/(1+j+l+k); if(k) f[i+1][j][l][k-1]+=f[i][j][l][k]*k/(1+j+l+k); if(j+l+k<7) { if(l) f[i+1][j+1][l-1][k+1]+=f[i][j][l][k]*l/(1+j+l+k); if(j) f[i+1][j][l+1][k]+=f[i][j][l][k]*j/(1+j+l+k); } else { if(l) f[i+1][j][l-1][k+1]+=f[i][j][l][k]*l/(1+j+l+k); if(j) f[i+1][j-1][l+1][k]+=f[i][j][l][k]*j/(1+j+l+k); } } double Ans=ans; printf("%.2lf\n",Ans); } }

【BZOJ 4832】 [Lydsy2017年4月月賽] 抵制克蘇恩 期望概率dp