原题: http://poj.org/problem?id=1189
//关键在于输入的处理以及运算过程中的 约分,约分可以保证每一次计算的结果都在long long的范围内,否则爆了会导致错误的结果
//定义结构体,并重载+和/运算符
//转移方程:如果字符是'*',则dp[i+1][c]=dp[i+1][c]+dp[i][c]/2;dp[i+1][c+1]=dp[i+1][c+1]+dp[i][c]/2;
// 如果字符是'.',则dp[i+2][c+1]=dp[i+2][c+1]+dp[i][c];
//这题一直是WA,就是没有及时地约分,导致数值超出了Longlong的范围,注意每一次计算后都约分就可以了。
//PS:long long的范围:-9223372036854775808 ~ 9223372036854775807
#include<cstdio>
#include<memory.h>
typedef long long ll;
ll gcd(ll a,ll b)
{
if(b==0)return a;
return gcd(b,a%b);
}
struct F //分数结构体
{
ll fz;
ll fm;
};
F operator + (F a,F b)//重载+
{
if(a.fz==0)return b;
if(b.fz==0)return a;
F tmp;
if(a.fm==b.fm)
{
tmp.fm=a.fm;
tmp.fz=a.fz+b.fz;
}else if(a.fm<b.fm){
tmp.fm=b.fm;
tmp.fz=a.fz*b.fm/a.fm+b.fz;
}else{
tmp.fm=a.fm;
tmp.fz=b.fz*a.fm/b.fm+a.fz;
}
ll g=gcd(tmp.fm,tmp.fz); //每一次计算都要约分
tmp.fm=tmp.fm/g;
tmp.fz=tmp.fz/g;
return tmp;
}
F operator / (F a,ll d) //重载/
{
ll g=gcd(a.fz,d);//每一次计算都要约分
a.fz=a.fz/g;
d=d/g;
a.fm=a.fm*d;
return a;
}
int strlen(char *from)
{
int i=0;
while(from[i]!='\0')
{
i++;
}
return i;
}
int main()
{
const int size=55;
int n,m;
while(~scanf("%d %d",&n,&m))
{
getchar();
char str[550];
F dp[55][55];
memset(dp,0,sizeof(F)*size*size);
// for(int i=0;i<=54;i++)
// {
// for(int j=0;j<=54;j++)
// {
// dp[i][j].fm=dp[i][j].fz=0;
// }
// }
dp[1][1].fm=1;
dp[1][1].fz=1;
for(int i=1;i<=n;i++)
{
gets(str);//输入n行
int c=1;
int len=strlen(str);
for(int j=0;j<len && c<=i;j++)//遍历这行的每一个字符
{
if(str[j]==' ')
{
continue;
}else if(str[j]=='*'){ //dp
dp[i+1][c]=dp[i+1][c]+dp[i][c]/2;
dp[i+1][c+1]=dp[i+1][c+1]+dp[i][c]/2;
c++;
}else if(str[j]=='.'){
dp[i+2][c+1]=dp[i+2][c+1]+dp[i][c];
c++;
}
}
}
if(dp[n+1][m+1].fz==0)
{
printf("0/1\n");
continue;
}else{
printf("%lld/%lld\n",dp[n+1][m+1].fz,dp[n+1][m+1].fm);
}
}
return 0;
}