ALGORITHM NOTE / ARCHIVE

筛子游戏(概率DP) 牛客

题目大意: 有三个面数给定的骰子,每次投出前进x+y+z(三个骰子投出的数字),开始位置在0点,问位置>n的期望步数? 特别的,如果x==a&&y==b&&z==c会回到0点

题目在这里

题目大意: 有三个面数给定的骰子,每次投出前进x+y+z(三个骰子投出的数字),开始位置在0点,问位置>n的期望步数? 特别的,如果x==a&&y==b&&z==c会回到0点

分析: 设f[i]表示分数到达i的期望步数 但是f[0]是一个未知数,所以需要使用一种常见手法进行转化。 设 带入方程右边 得到

已知:

可以递推求解A[0]和B[0] 最后得到f[0]

#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
using i128 = __int128;
#define ios ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);

double n,a,b,c,k1,k2,k3,p0;
double p[1024],A[1024],B[1024];

int main(){
    ios;
    cin>>n>>k1>>k2>>k3>>a>>b>>c;
    p0 = 1.0/k1/k2/k3;
    for(int i = n;i>=0;--i){
        for(int x = 1;x<=k1;++x){
            for(int y = 1;y<=k2;++y){
                for(int z = 1;z<=k3;++z){
                    if(x==a&&y==b&&z==c) continue;
                    int k = x+y+z;
                    A[i] += p0*A[i+k];
                    B[i] += p0*B[i+k];
                }
            }
        }
        A[i]+=p0;
        B[i]+=1.0;
    }
    double ans = B[0]/(1.0-A[0]);
    cout<<fixed<<setprecision(10)<<ans<<'\n';
    return 0;
}

好想学会DP