1. 程式人生 > >(C語言)整數劃分問題 遞迴和遞推

(C語言)整數劃分問題 遞迴和遞推

對於一個正整數n的劃分,就是把n變成一系列正整數之和的表示式。注意,分劃與順序無關,例如6=5+1跟6=1+5是
同一種分劃。另外,單獨這個整數本身也算一種分劃。
例如:對於正整數n=5,可以劃分為:
1+1+1+1+1
1+1+1+2
1+1+3
1+2+2
2+3
1+4
5
輸入描述
輸入一個正整數n

輸出描述
輸出n整數劃分的總數k

輸入樣例
5

輸出樣例
7

1、問題描述和分析 
對於一個正整數n的分化,就是把n表示成一系列正整數之和的表示式。注意,分劃與順序無關,例如6=1+5 和 6=5+1被認為是同一個劃分。另外,這個整數n本身也算是一種分化。
分析:
所謂整數劃分,是指把一個正整數n寫成如下形式: 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=4時,他有5個劃分,{4},{3,1},{2,2},{2,1,1},{1,1,1,1};
2、資料結構和演算法
該問題是求出n的所有劃分個數,即f(n, n)。下面我們考慮求f(n,m)的方法,採用遞迴法, 根據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)劃分。
    因此 f(n,n) =1 + f(n,n-1);
(4)當n<m時,由於劃分中不可能出現負數,因此就相當於f(n,n);
(5)但n>m時,根據劃分中是否包含最大值m,可以分為兩種情況:
    (a)劃分中包含m的情況,即{m, {x1,x2,...xi}}, 其中{x1,x2,... xi} 的和為n-m,因此這情況下為f(n-m,m);
    (b)劃分中不包含m的情況,則劃分中所有值都比m小,即n的(m-1)劃分,個數為f(n,m-1);

     因此 f(n, m) = f(n-m, m)+f(n,m-1);
  綜上所述:

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

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

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

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

遞迴程式碼:

#include<iostream>

using namespace std;

int Divinteger(int n,int m) {
	if(n == 1||m == 1)
		return 1;
	else if(n < m)
		return Divintege(n,n);
	else if(n == m)
		return 1+Divintege(n,n-1);
	else
		return Divintege(n,m-1) + Divintege(n-m,m);
}


int main(void) {
	int n;
	while(scanf("%d",&n) != EOF && (n >= 1)) {
		printf("%d\n",Divintege(n,n));
	}
	
	return 0;
}
遞推公式:

遞推就是打表,通過矩陣存下所有的個數,公式和思路與上面的一致,只需要把下面程式碼中的 i 看成 n ,j 看成 m,然後初始化 i = 0時候所有的值,

遞推程式碼:

#include<stdio.h>  
  
int resolve(int a,int max)
{  
    if(a == 1||max ==1)  
        return 1;  
    if(a == max)  
        return resolve(a,max-1)+1;  
    if(a > max)  
        return resolve(a,max-1)+resolve(a-max,max);  
    if(a < max)  
        return resolve(a,a);  
    else return 0;  
}  
  
int main()  
{  
    int n;  
    int sum;  
    scanf("%d",&n);  
    sum = resolve(n,n);  
    printf("%d",sum);  
    return 0;  
}