POJ 1189 钉子和小球

题目大意:中文

题目链接

注释代码:

/*                                        
 * 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值