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;

}

 

你可能感兴趣的:(HDU)