算法设计与分析:第三章 分治 3.2正整数划分

/*
将正整数n表示成一系列正整数之和:
n = n1 + n2 + ... +nk
其中n1>=n2>=...>=nk>=1,k>=1
正整数的这种表示称为正整数n的划分。求正整数n的不同划分个数

输入:
6
输出:
11

分析:设p(n)表示正整数n的划分树,难以找到递归关系,考虑增加变量
p(n) = q(n,n)
设q(n,m)表示:对于数字n,将最大加数n1不大于m的划分个数
q(n,m)={1,n = m = 1
	   {q(n,n),n<m,正整数n的划分由n1=n的划分和n1<=n-1的划分组成
	   {1+q(n,m-1),n=m,包含n只有1个划分,不包含n,划分值比n小
	   {q(n,m-1) + q(n-m,m),n>m>1,正整数n的最大加数n1不大于m的划分由n1=m的划分和n1<=m-1的划分组成
包含m时,剩余的数为n-m,又因为还有可能包含m,因此是q(n-m,m)
不包含m的划分,划分中所有值比m小,所以是q(n,m-1)
*/

#include <stdio.h>
#include <string.h>

const int MAXSIZE = 100;
long long g_q[MAXSIZE][MAXSIZE];


long long divideNum(int n,int m)
{
	if(g_q[n][m] != -1)
	{
		return g_q[n][m];
	}
	if(n == 1 || m == 1)
	{
		return g_q[n][m]= 1;
	}
	if(n < m)
	{
		return divideNum(n,n);
	}
	if(n == m)
	{
		return g_q[n][m] = 1 + divideNum(n,m-1);
	}
	if(n > m && m > 1)
	{
		return g_q[n][m] = divideNum(n,m-1) + divideNum(n-m,m);
	}
}


void process()
{
	int n;
	while(EOF != scanf("%d",&n))
	{
		if(n <= 0)
		{
			break;
		}
		memset(g_q,-1,sizeof(g_q));
		printf("%lld\n",divideNum(n,n));
	}
	
}

int main(int argc,char* argv[])
{
	process();
	getchar();
	return 0;
}

你可能感兴趣的:(算法设计与分析)