卡特兰数——单调路径证明(HDU2067)

Description

小兔的叔叔从外面旅游回来给她带来了一个礼物,小兔高兴地跑回自己的房间,拆开一看是一个棋盘,小兔有所失望。不过没过几天发现了棋盘的好玩之处。从起点(0,0)走到终点(n,n)的最短路径数是C(2n,n),现在小兔又想如果不穿越对角线(但可接触对角线上的格点),这样的路径数有多少?小兔想了很长时间都没想出来,现在想请你帮助小兔解决这个问题,对于你来说应该不难吧!

Input

每次输入一个数n(1<=n<=35),当n等于-1时结束输入。

Output

对于每个输入数据输出路径数,具体格式看Sample。

Sample Input 

1
3
12
-1

Sample Output

1 1 2
2 3 10
3 12 416024
这题非常简单,有两种做法:

1.DP递推:

由于某一个格子只能在通过左边或者上面的格子后才能到达(只考虑右半边),所以除了对角线上的格子外,到达某一个格子(i,j)的路径情况为dp[i][j]=dp[i-1][j]+dp[i][j-1];而要到达对角线上的格子(i,i)则必须到达该格子的上面一个格子:dp[i][i]=dp[i-1][i];

代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cctype>
using namespace std;

long long str[40][40];
int main()
{
	int i, j, n;
	for (j = 0; j <= 35; j++)
		str[0][j] = 1;
	for (i = 1; i <= 35; i++)
	{
		str[i][i] = str[i - 1][i];
		for (j = i + 1; j <= 35; j++)
			str[i][j] = str[i - 1][j] + str[i][j - 1];
	}
	i = 1;
	while (scanf("%d", &n) != EOF&&n != -1)
	{
		printf("%d %d %lld\n", i++, n, 2 * str[n][n]);
	}
	return 0;
}

2.卡特兰数

这题的数据的规律符合卡特兰数的特点,而重点是符合卡特兰数的证明。

 在《组合数学》(Richard A.Brualdi著)的第8章《特殊计数序列》中,首先介绍了卡特兰数:

(在该题中)若将向右走一格设置为+1,向下走一格设置为-1,那么n个+1和n个-1构成的2n项 a1,a2,……,a2n,其从开始到某一个位置k(k<=2n)都满足a1+a2+……+ak>=0的数列的个数等于第n个卡特兰数Cn=1/(n+1)c(2n,n)(组合中的c)。

这是可以运用卡特兰数的标志,即只有两种数据情况下,n个第一种元素与n个第二种元素构成2n项并满足上述特点,即符合卡特兰数的规律。

而卡特兰数则是

证明(以该题为例):

在n个+1和n个-1构成的2n项中,若不考虑到某一个位置为止数列和大于0的条件下,共有c(2n,n)种情况,设其中符合上述条件的数列为An,不符合上述条件的数列为Un,则An+Un=c(2n,n)。

在含n个+1和n个-1的Un中,由于数列不符合条件,则存在一个最小的k使直到k位置为止a1+……+ak=-1,则a1+……+ak-1=0,ak=-1,且k一定为奇数。现在把1到k项的符号反转,即ai=-ai,则生成了n+1个+1和n-1个-1的序列,而在该新序列中,有+1个数刚好超过-1个数的最小位置,从1到该位置将符号反转,即可生成原序列——说明这个过程是可逆的,即有多少个符合条件的含n+1个+1和n-1个-1的序列,就有多少个不符合条件的含n个+1和n个-1的序列,则Un=c(2n,n+1),则An=c(2n,n)-c(2n,n+1),化简得An=1/(n+1)c(2n,n)。


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值