动态规划求解整数拆分问题

#include
#define MAXN 10
//采用动态规划求解整数拆分问题。
//设f(n,k)为n的k拆分的拆分方案个数:
//其中,n表示被划分的数,k表示被划分出来的数中的可能出现的最大值,
//                       f(n,k)的值表示划分的方法个数
//(1)当n = 1或者k = 1时,显然f(n,k) = 1。
//(2)当n
//(3)当n = k时,
//		其拆分方案有将正整数n无序拆分成最大数为n - 1的拆分方案,
//		以及将n拆分成1个n(n = n)的拆分方案,后者仅仅一种,
//		所以有f(n,n) = f(n,n - 1) + 1。
//(4)当n>k时,根据拆分方案中是否包含k,可以分为两种情况:
//	① 拆分中包含k的情况:即一部分为单个k,
//		另外一部分为{ x1,x2,…,xi },后者的和为n - k,
//		后者中可能再次出现k,因此是(n - k)的k拆分,
//		所以这种拆分方案个数为f(n - k,k)。
//	② 拆分中不包含k的情况:
//		则拆分中所有拆分数都比k小,即n的(k - 1)拆分,
//		拆分方案个数为f(n,k - 1)。

int dp[MAXN][MAXN];			//动态规划数组
//划分方法
//	f(n,k) = 1							当n = 1或者k = 1
//	f(n,k) = f(n,n)					当n < k
//	f(n,k) = f(n,n - 1) + 1			当n = k
//	f(n,k) = f(n - k,k) + f(n,k - 1)	当n < k

void Split(int n, int k)		//求解算法
{
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= k; j++)
		{
			if (i == 1 || j == 1)
				dp[i][j] = 1;
			else if (i < j)
				dp[i][j] = dp[i][i];
			else if (i == j)
				dp[i][j] = dp[i][j - 1] + 1;
			else
				dp[i][j] = dp[i][j - 1] + dp[i - j][j];
		}
}
int fun(int n, int k)			//求解算法
{
	if (n == 1 || k == 1)
		return 1;
	else if (n < k)
		return fun(n, n);
	else if (n == k)
		return fun(n, n - 1) + 1;
	else
		return fun(n - k, k) + fun(n, k - 1);
}

int dp_2[MAXN][MAXN];
int dpf(int n, int k)			//求解算法
{
	if (dp_2[n][k] != 0)
		return dp_2[n][k];
	if (n == 1 || k == 1)
	{
		dp_2[n][k] = 1;
		return dp_2[n][k];
	}
	else if (n < k)
	{
		dp_2[n][k] = dpf(n, n);
		return dp_2[n][k];
	}
	else if (n == k)
	{
		dp_2[n][k] = dpf(n, k - 1) + 1;
		return dp_2[n][k];
	}
	else
	{
		dp_2[n][k] = dpf(n, k - 1) + dpf(n - k, k);
		return dp_2[n][k];
	}
}

int main()
{
	int i, j;
	int n = 5, k = 5;//n表示被划分的数,k表示被划分出来的数中的最大值
	printf("\n动态规划法求解:\n");
	Split(n, k);
	for (i = 1; i <= n; i++)
	{
		for (j = 1; j <= k; j++)
		{
			printf("%3d", dp[i][j]); 
			//dp[i][j]=x表示将i划分,且划分的数的最大值可以为j,共有x种划分方法
		}
		printf("\n");
	}
	printf("\n递归法求解:\n");
	printf("%3d", fun(n, k));

	printf("\n备忘录法求解:\n");
	dpf(n, k);
	for (i = 1; i <= n; i++)
	{
		for (j = 1; j <= k; j++)
		{
			printf("%3d", dp_2[i][j]);
			//dp_2[i][j]=x表示将i划分,且划分的数的最大值可以为j,共有x种划分方法
		}
		printf("\n");
	}
	return  0;
}

你可能感兴趣的:(C语言)