整數划分問題是算法中的一個經典命題之一,有關這個問題的講述在講解到遞歸時基本都將涉及。所謂整數划分,是指把一個正整數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};
注意4=1+3 和 4=3+1被認為是同一個划分。
該問題是求出n的所有划分個數,即f(n, n)。下面我們考慮求f(n,m)的方法;
分析:
我們可以分為四種:
1. m=1 or n=1
只有一種划分情況,就是n個1相加, 所以f(n,m)=1;
2. m=n>1
f(n,m)=f(n,n-1)+1 加上的1代表n+0=n這個划分方案
3.n<m
f(n,m)=f(n,n) 邏輯上不存在m>n這種情況
4.n>m
f(n,m)=f(n,m-1)+f(n-m,m)
f(n,m-1)表示划分方案中沒有m的情況
f(n-m,m)表示划分方案中有m的情況
下面我們來看一個例子,可以更好的理解哦
整數4 最大加數 3
1+3=4
1+1+2=4
2+2=4
1+1+1+1=4
一共4種划分方案
分析:
沒有m的情況:
1+1+2=4
2+2=4
1+1+1+1=4
符合f(n,m-1)
有m的情況:
1+3=4
符合f(n-m,m)
代碼如下:
/* 整數划分問題 :將一個整數划分為若干個數相加 例子: 整數4 最大加數 4 4=4 1+3=4 1+1+2=4 2+2=4 1+1+1+1=4 一共五種划分方案 注意:1+3=4,3+1=4被認為是同一種划分方案 */ #include<stdio.h> int q(int n,int m)//n表示需要划分的數字,m表示最大的家數不超過m { if(m==1||n==1)//只要存在一個為1,那么划分的方法數肯定只有一種,那就是n個1相加 { return 1; }else if(n==m&&n>1)//二者相等且大於1的時候,問題等價於:q(n,n-1)+1;意味着將最大加數減一之后n的划分數,然后加一,最后面那個一代表的是:0+n,這個划分的方案 { return q(n,n-1)+1; }else if(n<m)//如果m>n,那么令m=n就ok,因為最大加數在邏輯上不可能超過n { return q(n,n); }else if(n>m) { return q(n,m-1)+q(n-m,m);//分為兩種:划分方案沒有m的情況+划分方案有m的情況 } return 0; } int main() { printf("請輸入需要划分的數字和最大家數:\n"); int n,m; scanf("%d %d",&n,&m); int r=q(n,m); printf("%d\n",r); return 0; }
技術在於分享