poj 1189 钉子和小球

来源:互联网 发布:单片机datesheet是什么 编辑:程序博客网 时间:2024/05/01 09:41

钉子和小球

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 20000/10000K (Java/Other)
Total Submission(s) : 13   Accepted Submission(s) : 4
Problem Description
有一个三角形木板,竖直立放,上面钉着n(n+1)/2颗钉子,还有(n+1)个格子(当n=5时如图1)。每颗钉子和周围的钉子的距离都等于d,每个格子的宽度也都等于d,且除了最左端和最右端的格子外每个格子都正对着最下面一排钉子的间隙。 
让一个直径略小于d的小球中心正对着最上面的钉子在板上自由滚落,小球每碰到一个钉子都可能落向左边或右边(概率各1/2),且球的中心还会正对着下一颗将要碰上的钉子。例如图2就是小球一条可能的路径。 
我们知道小球落在第i个格子中的概率pi=pi=,其中i为格子的编号,从左至右依次为0,1,...,n。 
现在的问题是计算拔掉某些钉子后,小球落在编号为m的格子中的概率pm。假定最下面一排钉子不会被拔掉。例如图3是某些钉子被拔掉后小球一条可能的路径。 
 

Input
第1行为整数n(2 <= n <= 50)和m(0 <= m <= n)。以下n行依次为木板上从上至下n行钉子的信息,每行中'*'表示钉子还在,'.'表示钉子被拔去,注意在这n行中空格符可能出现在任何位置。
 

Output
仅一行,是一个既约分数(0写成0/1),为小球落在编号为m的格子中的概pm。既约分数的定义:A/B是既约分数,当且仅当A、B为正整数且A和B没有大于1的公因子。
 

Sample Input
5 2* * . * * * * . * ** * * * *
 

Sample Output

7/16

先求出每一层到格子的概率,然后计算出缺少某一些钉子时的概率,每下一层,若上方有钉子,那么就有dp[i+1][j]=dp[i][j]/2,

dp[i+1][j+1]=dp[i][j]/2,若上方没有钉子,则出现dp[i+2][j]=dp[i][j]

计算结果需要用到long long

加若计算的结果是0,输出0/1

#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#define LL long longusing namespace std;long long gcd(long long a, long long b){    if(b)        return gcd(b, a % b);    return a;}int main(){    int n,m;    LL map[51 + 51 * 50 / 2];    LL dp[55][55];    char s[5];    //memset(dp,0,)    while(~scanf("%d%d",&n,&m))    {        memset(dp,0,sizeof(dp));        memset(map,0,sizeof(map));        //char ch;        int index=1;        for(int i = 1; i <= n; i++)        {            for(int j = 1; j <= i; j++)            {                scanf("%s", s);                if(s[0] == '*')                    map[index++] = 1;                else                    map[index++] = 0;            }        }        dp[1][1]=1;        for(int i=1; i<=n; i++)            dp[1][1]<<=1;        //cout<<dp[0][0]<<endl;        for(int i=1; i<=n; i++)        {            int x=i*(i-1)/2;            for(int j=1; j<=i; j++)            {                if(map[x+j]==1)                {                    dp[i+1][j]+=dp[i][j]>>1;                    dp[i+1][j+1]+=dp[i][j]>>1;                }                else                    dp[i+2][j+1]+=dp[i][j];            }        }        LL sum0=0;        LL sum1=dp[n+1][m+1];        //cout<<sum1<<endl;        for(int i=1; i<=n+1; i++)        {            sum0+=dp[n+1][i];        }        //cout<<sum0<<endl;        LL c=gcd(sum1,sum0);        if(sum1==0)        {            sum0=1;            c=1;        }        printf("%lld/%lld\n",sum1/c,sum0/c);    }    return 0;}


0 0
原创粉丝点击