题目大意:
一个三角形木板,竖直立放,上面钉着n(n+1)/2颗钉子,还有(n+1)个格子(当n=5时如图1)。每颗钉子和周围的钉子的距离都等于d,每个格子的宽度也都等于d,且除了最左端和最右端的格子外每个格子都正对着最下面一排钉子的间隙。
让一个直径略小于d的小球中心正对着最上面的钉子在板上自由滚落,小球每碰到一个钉子都可能落向左边或右边(概率各1/2),且球的中心还会正对着下一颗将要碰上的钉子。例如图2就是小球一条可能的路径。
现在的问题是计算拔掉某些钉子后,小球落在编号为m的格子中的概率pm。假定最下面一排钉子不会被拔掉。例如图3是某些钉子被拔掉后小球一条可能的路径。
思路:
dp
若有钉子,则该点的概率为上面两个点的概率和
无钉子,则该点概率为上上面点的概率
注意数据较大
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<memory.h> #include<vector> #include<queue> #include<cstdlib> using namespace std; char map[55][55]; __int64 f[55][55]; int n,m; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=i;j++) cin>>map[i][j]; f[1][1]=(__int64)1<<n; for(int i=1;i<=n+1;i++) for(int j=1;j<=i;j++) { if(map[i][j]=='*') {f[i+1][j]+=f[i][j]/2;f[i+1][j+1]+=f[i][j]/2;} if(map[i][j]=='.') f[i+2][j+1]+=f[i][j]; } while(f[n+1][m+1]%2==0&&f[n+1][m+1]!=0) { f[n+1][m+1]/=2; f[1][1]/=2; } if(f[n+1][m+1]==0) f[1][1]=1; printf("%I64d/%I64d",f[n+1][m+1],f[1][1]); }