遞歸--整數划分問題


問題描述:

將正整數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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM