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; }