HDU 4050 wolf5x 概率dp 难度:1

http://acm.hdu.edu.cn/showproblem.php?pid=4050

题意:

现在主角站在0处,需要到达大于n的位置

主角要进入的格子有三种状态:

0. 不能进入

1. 能进入左脚,下一步出右脚

2. 能进入右脚,下一步出左脚

3. 两只脚都能进入,而且下一步迈出左右脚都可.

也就是说,如果只有1,2种状态的格子,那么主角只能重复左脚-右脚-左脚...或者右脚-左脚-右脚

但是有了状态为3的格子,就能够左脚-左脚-左脚这样走路

设e[i][sta]为主角在编号为i的方格状态为sta的概率,sta为1,2,3,分别代表踏入的是下一步右脚,下一步左脚,两只脚都可以的格子

并设kp1[i+a][i+j]从i+a开始到i+j-1右脚无法踏入的概率,kp2[i+a][i+j]从i+a开始到i+j-1左脚无法踏入的概率,kp3[i+a][i+j]为两只脚都无法踏入概率,

则:
            e[i][1]+=(e[i+j][2]+1)*kp1*p2[i+j]+(e[i+j][3]+1)*kp1*p3[i+j];
            e[i][2]+=(e[i+j][1]+1)*kp2*p1[i+j]+(e[i+j][3]+1)*kp2*p3[i+j];
            e[i][3]+=(e[i+j][1]+1)*kp3*p1[i+j]+(e[i+j][2]+1)*kp3*p2[i+j]+(e[i+j][3]+1)*kp3*p3[i+j];

明显e[0][3]为答案

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=2e3+1;
const double eps=1e-9;
int n,a,b;
double p0[maxn],p1[maxn],p2[maxn],p3[maxn];
double e[maxn][4];
void calc(){
    for(int i=n;i>=0;i--){
        memset(e[i],0, sizeof e[i]);
        double kp1=1,kp2=1,kp3=1;
        for(int j=a;j<=b;j++){
            if(i+j>n){
                e[i][1]+=kp1;
                e[i][2]+=kp2;
                e[i][3]+=kp3;
                break;
            }
            e[i][1]+=(e[i+j][2]+1)*kp1*p2[i+j]+(e[i+j][3]+1)*kp1*p3[i+j];
            e[i][2]+=(e[i+j][1]+1)*kp2*p1[i+j]+(e[i+j][3]+1)*kp2*p3[i+j];
            e[i][3]+=(e[i+j][1]+1)*kp3*p1[i+j]+(e[i+j][2]+1)*kp3*p2[i+j]+(e[i+j][3]+1)*kp3*p3[i+j];
            kp1*=(p0[i+j]+p1[i+j]);
            kp2*=(p0[i+j]+p2[i+j]);
            kp3*=(p0[i+j]);
        }

    }
}

int dcmp(double a,double b){
    if(fabs(a-b)<=eps)return 0;
    return a>b?1:-1;
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--&&scanf("%d%d%d",&n,&a,&b)==3){
        for(int i=1;i<=n;i++){
            scanf("%lf%lf%lf%lf",p0+i,p1+i,p2+i,p3+i);
        }
        calc();
        printf("%.8f
",e[0][3]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/xuesu/p/4498451.html