题意:中文题目看题即可。
思路:将最顶上的钉子给予权值2^n,然后模拟其下落过程,计算最终落到指定位置的权值是多少即可。注意中间任意位置的权值可能来源于三个部分,1、左上位置;2、右上位置;3、如果正上方没有钉子,则来源于正上方。采用递归式的动态规划,因为可能某些钉子的权值不必求出。
#include <stdio.h>
#include <string.h>
#define N 55
char buf[1024];
int s[N][N];
long long dp[N][N],fz,fm;
int n,m;
long long gcd(long long x,long long y){
if(!y)
return x;
return gcd(y,x%y);
}
long long fun(int x,int y){
long long res = 0;
if(dp[x][y])
return dp[x][y];
if(x!=y && s[x-1][y])
res += fun(x-1,y)/2;
if(y!=1 && s[x-1][y-1])
res += fun(x-1,y-1)/2;
if(x>2 && y<x && !s[x-2][y-1])
res += fun(x-2,y-1);
return dp[x][y] = res;
}
int main(){
while(scanf("%d %d\n",&n,&m)!=EOF){
int i,j,k;
long long temp;
memset(s,0,sizeof(s));
memset(dp,0,sizeof(dp));
for(i = 1;i<=n;i++){
gets(buf);
for(j = 0,k = 1;k<=i;j++)
if(buf[j]!=' '){
if(buf[j] == '*')
s[i][k] = 1;
k++;
}
}
fm = dp[1][1] = (long long)1<<n;
fz = fun(n+1,m+1);
temp = gcd(fz,fm);
if(fz == 0)
printf("0/1\n");
else
printf("%lld/%lld\n",fz/temp,fm/temp);
}
return 0;
}