問題描述:
將正整數n表示成一系列正整數之和:n=n1+n2+…+nk,其中n1≥n2≥…≥nk≥1,k≥1。正整數n的這種表示稱為正整數n的划分。
問題1:
輸出整數n的所有可能的划分,如:
輸入:6
輸出: 5+1;
4+2,4+1+1;
3+3,3+2+1,3+1+1+1;
2+2+2,2+2+1+1,2+1+1+1+1;
1+1+1+1+1+1。
我的思路:這種問題已經遇到過很多了,遞歸搜索所有可能的情況,同時為了記錄下每一步的情況,那么就要用到一個數組mark來存儲每一步的數,然后遞歸同時要傳遞遞歸的深度k。還有個問題就是遞歸下一個數的時候,因為是遞減的排列的。所以我們還必須記錄下上一個的數,然后下一個數必須小於或者等於上一個數。最后遞歸函數還有有個參數記錄當前的長度,來判斷是否能夠組成我們想要的長度,不能的話就回溯,繼續往下一個數去嘗試。OK!
代碼:
//整數划分問題 #include <stdio.h> int mark[10]; int n; void Divid(int now,int k,int prio) { //now記錄當前長度,k記錄深度,prio記錄前一個的值。 int i; if(now > n) return; //不合適,返回。 if(now == n) { for(i = 0; i < k-1; i++) printf("%d+",mark[i]); printf("%d\n",mark[i]); } else { for(i = prio; i > 0; i--) { if(i <= prio) //必須必前一個要小 { mark[k]=i; now+=i; Divid(now,k+1,i); now-=i; } } } } int main() { scanf("%d",&n); Divid(0,0,n-1); return 0; }
2013/5/29 14:17
問題2:求正整數n的不同划分個數,將最大數n1不大m的划分記住做q(n,m),叫做n的m划分。
輸入:n m
輸出:n的m划分的總個數。
我的思路:首先要找出遞歸的公式來,首先分析幾種簡單的情況,n==1||m==1可以直接得出結果為1;而當n<m時,可以直接求出q(n,n);當n=m時,因為對於n本身只有一種情況,即n,所有可以直接用1+q(n,n-1)來求。最后當n>m時,可以用q(n,m-1)+q(n-m,m),其中q(n-m,m表示的時當m固定后,求剩下可能的情況。參考下圖:
代碼:
//求整數划分的個數 #include <stdio.h> int Divid(int n, int m) { if (n == 1 || m == 1) return 1; //必須是或 if (n < m) return Divid(n,n); if (n == m) return 1 + Divid(n,n-1); return Divid(n,m-1) + Divid(n-m,m); } int main() { int n,m; scanf("%d%d",&n,&m); printf("%d\n",Divid(n,m)); return 0; }
2013/5/29 14:35