递归--整数划分问题
問題描述:
將正整數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;
}
/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;
}
/5/29 14:35
總結
以上是生活随笔為你收集整理的递归--整数划分问题的全部內容,希望文章能夠幫你解決所遇到的問題。