题目
大致题意
每个位置给出原地不动、向下走一步和向右走一步的概率,每走一步会消耗2能量,问:从 ( 1 , 1 ) − > ( r , c ) (1,1)->(r,c) (1,1)−>(r,c)需要能量的期望。
思路
根据题意可以推出式子:
d
p
[
i
]
[
j
]
:
dp[i][j]:
dp[i][j]:从第
r
r
r行
c
c
c列到第
i
i
i行
j
j
j列时能量的期望。即
d
p
[
r
]
[
c
]
=
0
;
d
p
[
1
]
[
1
]
dp[r][c]=0;dp[1][1]
dp[r][c]=0;dp[1][1]即所求答案
p
[
i
]
[
j
]
[
x
]
:
p[i][j][x]:
p[i][j][x]:第
i
i
i行
j
j
j列原地不动(0)、向下走一步(1)和向右走一步(2)的概率。
d
p
[
i
]
[
i
]
=
d
p
[
i
]
[
i
]
∗
p
[
i
]
[
j
]
[
0
]
+
d
p
[
i
]
[
j
+
1
]
∗
p
[
i
]
[
j
]
[
1
]
+
d
p
[
i
+
1
]
[
j
]
∗
p
[
i
]
[
j
]
[
2
]
+
2
dp[i][i]=dp[i][i]*p[i][j][0]+dp[i][j+1]*p[i][j][1]+dp[i+1][j]*p[i][j][2]+2
dp[i][i]=dp[i][i]∗p[i][j][0]+dp[i][j+1]∗p[i][j][1]+dp[i+1][j]∗p[i][j][2]+2
加2含义:每走一步需要消耗2能量
等式两边都存在
d
p
[
i
]
[
i
]
dp[i][i]
dp[i][i],但此时其为未知数,所以将其化简到等是的一边即可求解答案。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
//#define int long long
const int N = 1e5+10;
const double eps=1e-8;
double p[1010][1010][3];
double dp[1010][1010];
signed main(){
// ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int t,n,m,k,x,y;
while(cin>>n>>m&&(m+n)){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%lf %lf %lf",&p[i][j][0],&p[i][j][1],&p[i][j][2]);
}
}
memset(dp,0,sizeof(dp));
for(int i=n;i>0;i--){
for(int j=m;j>0;j--){
if((i==n&&j==m)||1.0-p[i][j][0]<eps)continue;
dp[i][j]=(2.0+dp[i+1][j]*p[i][j][2]+dp[i][j+1]*p[i][j][1])/(1-p[i][j][0]);
}
}
printf("%.3lf\n",dp[1][1]);
}
return 0;
}