題目鏈接:https://codeforces.com/contest/1245/problem/E
題目大意:
一個10*10矩陣,左下角起點,左上角終點,按照S型前進,每次通過扔骰子確定行走步數,1~6概率相同,到最後只剩1~6的時候只能正好扔到所需點數才能到達。同時如果遇到梯子的話可以沿着梯子爬上去,問到達終點的期望步數。
題目思路:
設1爲終點,100爲起點,表示座標的編號。表示x編號可以靠它那個位置的梯子到達哪個位置。
這題相較於普通的概率DP有兩點不同,一個是最後六步必須正好到,一個是可以坐梯子。首先可以發現,在終點肯定不用動就在終點,所以dp[1]=0,終點的期望是確定的,所以需要從終點向起點倒推。同時最後六步需要計算。這六步到達終點的期望步數,要麼是的概率直接到終點,要麼是概率原地踏步,所以得到公式:
由於,代入整理得到:
所以最後六步期望就是固定的6。然後就是dp轉移,枚舉1~6作爲走的步數,設爲j,假設他當前在第i個點,那麼他可能是i-j來的,當然也可能是i-j能爬上去的那個梯子的位置過來的(這裏要注意,咱是倒推!)所以取個min繼續推導即可。
以下是代碼:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
const int MAXN=1e2+5;
const int MOD=1e9+7;
int id[MAXN][MAXN],a[MAXN];
double dp[MAXN];
int main()
{
rep(i,1,10){
rep(j,1,10){
if(i&1)id[i][j]=(i-1)*10+j;
else id[i][j]=i*10-j+1;
}
}
rep(i,1,10){
rep(j,1,10){
int x;
cin>>x;
a[id[i][j]]=id[i-x][j];
}
}
dp[1]=0;
rep(i,2,7)dp[i]=6;
rep(i,8,100){
dp[i]=0;
rep(j,1,6){
dp[i]+=min(dp[i-j],dp[a[i-j]])+1;
}
dp[i]=dp[i]/6.0;
}
cout<<fixed<<setprecision(10)<<dp[100]<<endl;
return 0;
}