HDU 3076 ssworld VS DDD 概率dp,无穷级数,oj错误题目 难度:2
http://acm.hdu.edu.cn/showproblem.php?pid=3076
不可思议的题目,总之血量越少胜率越高,所以读取时把两人的血量交换一下
明显每一轮的胜率和负率都是固定的,所以设psc为胜率,pls为负率,peq为平率,
则在每一局中的胜率负率平率可以确定,
而在有结果的一个阶段中的胜率和负率则各是一个无穷级数
psc(new)=1*psc+peq*psc+peq*peq*psc.......=lim(n->正无穷)(1-peq^n)*psc/(1-peq)=psc/(1-peq)
pls(new)=1*pls+peq*pls+peq*peq*pls.......=lim(n->正无穷)(1-peq^n)*pls/(1-peq)=pls/(1-peq)
设p[i][j]为A的hp为i,B的hp为j的概率
很明显转移公式是:
当i>0,j>0时
p[i-1][j]+=p[i][j]*pls(new)
p[i][j-1]+=p[i][j]*psc(new)
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <queue> using namespace std; const int maxn=2e3+3; double p[maxn]; double pp[2][6]; double psc,pls,peq; int a,b; double ans; void calc(){ psc=pls=peq=0; ans=0; memset(p,0,sizeof p); for(int i=0;i<6;i++){ for(int j=0;j<6;j++){ if(i==j)peq+=pp[0][i]*pp[1][j]; else if(i<j)pls+=pp[0][i]*pp[1][j]; else psc+=pp[0][i]*pp[1][j]; } } if(peq!=1){ psc/=(1-peq); pls/=(1-peq); } p[b]=1; for(int i=a;i>0;i--){ for(int j=b;j>0;j--){ p[j-1]+=p[j]*psc; } ans+=p[1]*psc; for(int j=b;j>0;j--){ p[j]*=pls; } } } int main(){ while(scanf("%d%d",&b,&a)==2){ for(int i=0;i<6;i++)scanf("%lf",pp[0]+i); for(int i=0;i<6;i++)scanf("%lf",pp[1]+i); calc(); printf("%.6f\n",ans); } return 0; }