整数划分(递归)并输出划分的结果

整数划分(递归)并输出划分的结果

说明一下问题,什么是整数划分?

  • n=m1+m2+...+mi; (其中mi为正整数,并且1 <= mi <= n),则{m1,m2,...,mi}为n的一个划分。
  • 如果{m1,m2,...,mi}中的最大值不超过m,即max(m1,m2,...,mi)<=m,则称它属于n的一个m划分。这里我们记n的m划分的个数为f(n,m);
  • 举个例子,当n=5时我们可以获得以下这几种划分(注意,例子中m>=5)

5 = 5 
   = 4 + 1 
   = 3 + 2 
   = 3 + 1 + 1 
   = 2 + 2 + 1 
   = 2 + 1 + 1 + 1 
   = 1 + 1 + 1 + 1 + 1

根据n和m的关系,考虑以下几种情况:

   (1)当n=1时,不论m的值为多少(m>0),只有一种划分即{1};

   (2)当m=1时,不论n的值为多少,只有一种划分即n个1,{1,1,1,...,1};

   (3)当n=m时,根据划分中是否包含n,可以分为两种情况:

      (a)划分中包含n的情况,只有一个即{n};

      (b)划分中不包含n的情况,这时划分中最大的数字也一定比n小,即n的所有(n-1)划分。 因此 q(n,n) =1 + q(n,n-1);

   (4)当n<m时,由于划分中不可能出现负数,因此就相当于q(n,n);

   (5)但n>m时,根据划分中是否包含最大值m,可以分为两种情况:

       (a)划分中包含m的情况,即{m, {x1,x2,...xi}}, 其中{x1,x2,... xi} 的和为n-m,因此这情况下为q(n-m,m)

       (b)划分中不包含m的情况,则划分中所有值都比m小,即n的(m-1)划分,个数为q(n,m-1);

      因此 q(n, m) = q(n-m, m)+q(n,m-1);

      综上所述:

                             q(n, m) =   1;                  (n=1 or m=1)

                             q(n,m) =  q(n, n);           (n<m)

                             1+ q(n, m-1);                  (n=m)

                             q(n-m,m)+q(n,m-1);      (n>m)

递归算法:

代码如下:

#include<iostream>
using namespace std;
int q(int n, int m) {
	if(n < 1 || m < 1) return 0;
	if(n == 1 || m == 1) return 1;
	if(n < m) return (n, n);
	if(n == m) return q(n, m-1) + 1;
	return q(n, m-1) + q(n-m, m);
}
int main() {
	cout<<q(6, 6)<<endl;
	return 0;
}

动态规划:

#include <iostream>
#define  MYDATA long long
const MYDATA MOD = 1000000007;
#define MAXNUM 1005            //最高次数  
long ww[MAXNUM * 11][MAXNUM * 11];
long dp(int n, int max);
using namespace std;
int main() {
	int n;
	int m;
	long count;
	while (1) {
		cin >> n;
		cout << dp(n, n) << endl;
	}
	return 0;
}
long dp(int n, int max) {
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= i; j++) {
			if (j == 1 || i == 1) {
				ww[i][j] = 1;
			} else {
				if (j == i)
					ww[i][j] = (ww[i][j - 1] + 1) % MOD;
				else if ((i - j) < j)
					ww[i][j] = (ww[i - j][i - j] + ww[i][j - 1]) % MOD;
				else
					ww[i][j] = (ww[i - j][j] + ww[i][j - 1]) % MOD;
			}
		}
	return ww[n][max];
}

输出结果:

#include <stdio.h>
int mark[256];
int n;
void DFS(int sum, int k, int prio) {
	if(sum > n) {
		return;
	} else if(sum == n) {
		int i;
		printf("=");
		for( i = 0; i < k-1; i++) {
			printf("%d+",mark[i]);
		}
		printf("%d\n",mark[i]);
	} else {
		for(int j = prio; j > 0; j--) {
			mark[k] = j;
			sum += j;
			DFS(sum,k+1,j);
			sum -= j;  //恢复现场
		}
	}
}
int main() {
	scanf("%d", &n);
	DFS(0, 0, n);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/adusts/article/details/79860669