题目大意:中文
注释代码:
/*
* Problem ID : POJ 1189 钉子和小球
* Author : Lirx.t.Una
* Language : C++
* Run Time : 0 ms
* Run Memory : 144 KB
*/
#include <stdio.h>
//最大行数为50,下标从0取
//最后一行(下标为50)表示坑槽
#define MAXN 51
typedef long long llg;
llg dp[MAXN][MAXN];//表示掉在坐标为(i, j)处的当前可能性值
char ln[MAXN][MAXN];//line[i][j]表示(i, j)处的符号'*'或'.'
llg
gcd( llg a, llg b ) {//辗转相除
if ( !b )
return a;
llg tmp;
while ( b ) {
tmp = a % b;
a = b;
b = tmp;
}
return a;
}
int
main() {
int n, m;//n行,第m号坑槽
int i, j;//技术变量
llg tmp;
llg d;//divisor,存放最大公约数
scanf("%d%d", &n, &m);
for ( i = 0; i < n; i++ )
for ( j = 0; j <= i; j++ )
scanf("%s", &ln[i][j]);
//设初始位置可能性权值最大,设为1^n
//由于分叉下面位置可能性权值会降低(除以2等)
//所以最下面(坑槽)处可能性值最低
//用m处的可能性值除以起始位置的可能性值即为所求
//还有现除去最大公约数
dp[0][0] = (llg)1 << (llg)n;
for ( i = 1; i <= n; i++ )
for ( j = 0; j < i; j++ )
if ( '*' == ln[i - 1][j] ) {//求可能掉到左下或右下
//设(i - 1, j)为当前位置
tmp = dp[i - 1][j] >> (llg)1;
dp[i][j] += tmp;
dp[i][j + 1] += tmp;
}
else//若无钉子则垂直调到下下行,由于最后一行不会拔钉子
//所以不用担心数组越界
dp[i + 1][j + 1] += dp[i - 1][j];
d = gcd( dp[0][0], dp[n][m] );
printf("%lld/%lld\n", dp[n][m] / d, dp[0][0] / d);
return 0;
}
无注释代码:
#include <stdio.h>
#define MAXN 51
typedef long long llg;
llg dp[MAXN][MAXN];
char ln[MAXN][MAXN];
llg
gcd( llg a, llg b ) {
if ( !b )
return a;
llg tmp;
while ( b ) {
tmp = a % b;
a = b;
b = tmp;
}
return a;
}
int
main() {
int n, m;
int i, j;
llg tmp;
llg d;
scanf("%d%d", &n, &m);
for ( i = 0; i < n; i++ )
for ( j = 0; j <= i; j++ )
scanf("%s", &ln[i][j]);
dp[0][0] = (llg)1 << (llg)n;
for ( i = 1; i <= n; i++ )
for ( j = 0; j < i; j++ )
if ( '*' == ln[i - 1][j] ) {
tmp = dp[i - 1][j] >> (llg)1;
dp[i][j] += tmp;
dp[i][j + 1] += tmp;
}
else
dp[i + 1][j + 1] += dp[i - 1][j];
d = gcd( dp[0][0], dp[n][m] );
printf("%lld/%lld\n", dp[n][m] / d, dp[0][0] / d);
return 0;
}