杭电1143——Tri Tiling(递推求解)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1143
题目分析:
可能自己的分析能力还是不够,每次做这种递推题的时候,都要分析半天。其实想起来,与卡特兰数的推导的思想是完全一致的。这个需要慢慢的体会。先说这道题。
很明显,如果输入的n是奇数,奇数的平方仍然是奇数,不可能用偶数的面积填满奇数的面积,所以结果是0。
下面考虑输入是偶数的情况,假设前k个是第一个(这是关键,其实卡特兰数的推倒也是找到第一个切入点,然后把问题分成两个子问题)可以单独分出来的模块,那么排列的总数就应该是g(k)*f(n-k)。显然这个k一定是偶数,并且取值为2-n-2;
下面我们来看这g(k)的取值(其实g(k)就是宽为k且不可分的排列数),注意到只有到k这里才可分,在k之前都不可分,可以看到图形的高都是3,所以要么在最上面放一层,或者在最下面放一层,让高变成2,而让图不可分,剩下的高为2的部分,必须在两头各竖着放一个,要不图形就可以分成两个小图形了,这样就不满足我们递推的思路了。这样其实可以得到一个规律,只有k为2时g(k)是3,其余的情况,g(k)都是2。这样我们就可以简单的写出递推式:f(n)=3*f(n-2)+2*f(n-4)+.....+2*f(2);同理f(n-2)=3*f(n-4)+2*f(n-6)+.....+2*f(2);f(n)-4*f(n-2)=-f(n-4);所以最终的递推式就是f(n)=4*f(n-2)-f(n-4)
有了上面的递推式,代码就简单了。

#include <stdio.h>
#define M 30
int dp[M+5];
void main()
{
	int i;
	int n;
	dp[0] = 1;
	dp[2] = 3;
	for(i = 4; i <= M; i += 2)
	{
		dp[i] = 4 * dp[i - 2] - dp[i - 4];
	}
	while(scanf("%d",&n))
	{
		if(n < 0)
		{
			break;
		}
		if(n & 1)
		{
			printf("0\n");
		}
		else
		{
			printf("%d\n",dp[n]);
		}
	}
}

你可能感兴趣的:(杭电1143——Tri Tiling(递推求解))