题意:有N个格子,1~N,起点在0,每个格子有一个状态(0,1,2,3),每次可以跨[a,b]步,
问走完N个格子需要步数的期望,每次尽量走小的步数,即尽量走a步,不能则走a+1,……
状态0意味着你不能踏进对应的网格。
状态1意味着你可以步入网格用你的左腿。
状态2意味着你可以步入网格用你的右腿。
状态3意味着你可以进入网格用任何你的腿,而接下来的步骤中,您可以使用任何的腿;即你不需要遵循上述规则。
思路:借鉴了各路大神的思想理解了下。
dp[i][j] :表示走到第 i 个格子在 j 状态的期望。
当j=1时,你可以走到dp[i+k][2],dp[i+k][3],
当j=2时,你可以走到dp[i+k][1],dp[i+k][3],
当j=3时,你可以走到dp[i+k][2],dp[i+k][3],dp[i+k][1],
若i+k格子是0状态或与i状态相同则不能跨k步,即若要跨k步,则跨[a,k-1]步的格子与第i个格子状态相矛盾。
#include<stdio.h> #include<string.h> #include<string> #include<map> #include<stack> #include<math.h> #include<queue> #include<vector> #include<stdlib.h> #include<iostream> #include<algorithm> using namespace std; #define N 2010 #define eps 1e-5 int main() { int t; double dp[N*2][4],p[N*2][4]; scanf("%d",&t); while(t--) { int n,a,b; scanf("%d%d%d",&n,&a,&b); for(int i=1;i<=n;i++) scanf("%lf%lf%lf%lf",&p[i][0],&p[i][1],&p[i][2],&p[i][3]); for(int i=n+1;i<=n+a;i++) for(int j=0;j<4;j++) p[i][j]=(j==3); memset(dp,0.0,sizeof(dp)); dp[0][3]=1; for(int i=0;i<=n;i++) { double p1=1.0,p2=1.0,p3=1.0; for(int j=a;j<=b;j++) { dp[i+j][2]+=dp[i][1]*p1*p[i+j][2]; dp[i+j][3]+=dp[i][1]*p1*p[i+j][3]; p1*=(p[i+j][1]+p[i+j][0]); dp[i+j][1]+=dp[i][2]*p2*p[i+j][1]; dp[i+j][3]+=dp[i][2]*p2*p[i+j][3]; p2*=(p[i+j][2]+p[i+j][0]); dp[i+j][1]+=dp[i][3]*p3*p[i+j][1]; dp[i+j][2]+=dp[i][3]*p3*p[i+j][2]; dp[i+j][3]+=dp[i][3]*p3*p[i+j][3]; p3*=p[i+j][0]; } } double ans=0.0; for(int i=1;i<=n+a;i++) for(int j=1;j<4;j++) ans+=dp[i][j]; printf("%.6lf\n",ans); } return 0; }