这题其实并不是在考DP吧。。。
转移方程显然
有钉子的情况下落到左右两边概率相等,均为当前概率的一半
f[i+1][j]+=f[i][j]/2
f[i+1][j+1]+=f[i][j]/2
没钉子的话就直接掉在正下方的钉子上,该点的概率加上当前的
f[i+2][j+1]+=f[i][j]
然而难点不在dp,在分数输出好吧!
来自交了n遍才乱搞对的蒟蒻
我用了一种非常玄科学的做法
众所周知,小球在每个位置的平均概率是2ˆn
所以我们正常算出f[n+1][m+1]后再让它和2ˆn搞一个gcd,将两数同时除以gcd(相当于约分)即可
code
#include<bits/stdc++.h> #define ll long long using namespace std; namespace gengyf{ ll n,m,f[55][55],tot,ans; char mp[55][55]; ll gcd(ll x,ll y){ if(!y) return x; return gcd(y,x%y); } ll power(ll x,ll y){ ll q=1; while(y){ if(y%2) q*=x; y/=2; x=x*x; } return q; } int main(){ scanf("%lld%lld",&n,&m); tot=power(2,n); for(int i=1;i<=n;i++) for(int j=1;j<=i;j++) scanf("%s",&mp[i][j]); f[1][1]=tot; for(int i=1;i<=n;i++){ for(int j=1;j<=i;j++){ if(mp[i][j]=='*') f[i+1][j]+=f[i][j]/2,f[i+1][j+1]+=f[i][j]/2; else f[i+2][j+1]+=f[i][j]; } } ans=gcd(tot,f[n+1][m+1]); f[n+1][m+1]/=ans,tot/=ans; printf("%lld/%lld ",f[n+1][m+1],tot); return 0; } } int main(){ gengyf::main();return 0; }