1. 程式人生 > >整數劃分問題的遞迴演算法-c語言

整數劃分問題的遞迴演算法-c語言

整數劃分問題是演算法中的一個經典命題之一,有關這個問題的講述在講解到遞迴時基本都將涉及。所謂整數劃分,是指把一個正整數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)的方法;

        ---------------------------------------------------------------------

                                           (一)遞迴法

        ---------------------------------------------------------------------

       根據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,可能再次出現m,因此是(n-m)的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);

         綜合以上情況,我們可以看出,上面的結論具有遞迴定義特徵,其中(1)和(2)屬於迴歸條件,(3)和(4)屬於特殊情況,將會轉換為情況(5)。而情況(5)為通用情況,屬於遞推的方法,其本質主要是通過減小m以達到迴歸條件,從而解決問題。其遞推表示式如下:

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

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

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

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

[email protected]:~/workdir/ACM-ICPC$ cat IntDivide.c
#include <stdio.h>

int IntDivide(int n, int m)
{
        if((n<1)||(m<1))
                return 0;
        if((n==1)||(m==1))
                return 1;
        if(n<m)
                return IntDivide(n,n);
        if(n==m)
                return IntDivide(n,n-1)+1;
        return IntDivide(n-m,m)+IntDivide(n,m-1);
}

int main()
{
        int n=0,m=0;
        int result=0;

        scanf("%d %d",&n,&m);

        result = IntDivide(n,m);

        printf("%d\n",result);

        return 0;
}

相關推薦

整數劃分問題的演算法-c語言

整數劃分問題是演算法中的一個經典命題之一,有關這個問題的講述在講解到遞迴時基本都將涉及。所謂整數劃分,是指把一個正整數n寫成如下形式:        n=m1+m2+...+mi; (其中mi為正整數,並且1 <= mi <= n),則{m1,m2,...,

中序遍歷二叉樹(非演算法 c語言

#include "stdio.h" #include "string.h" #include "malloc.h" #define NULL 0 #define MAXSIZE 30 typedef struct BiTNode      //定義二叉樹資料結構 {  

演算法作業-整數劃分-

正整數的劃分問題是將一個正整數n表示成一系列正整數之和:n=n1+n2+…+nk,其中n1≥n2≥…≥nk≥1,k≥1。請編寫至少三種不同的求解演算法,並對所編寫演算法的時間效率進行測試和比較。解法一:遞迴演算法考慮增加一個自變數:將最大加數n1不大於m的劃分個數記作q(n,

二叉樹的前序,中序,後序的遍歷的和非程式碼-C語言

#include <stdio.h> #include<stdlib.h> /* run this program using the console pauser or add your own getch, system("pause") or input l

資料結構-二路歸併-實現-C語言

/* * * 二路歸併 遞迴實現 * * * */ #include <stdio.h> #include <stdlib.h> //對一個元素或者多個有序元素進行合併 void Merge(int Element[],int TmpA[],int

快速排序的非實現-----c語言

  前面我們講解了快速排序的遞迴實現,但若是待排序的數量非常大且雜亂無章,每層迴圈都使用遞迴呼叫,會很容易造成棧溢位,所以我們可以將快速排序設計為非遞迴實現。 遞迴實現快速排序演算法詳解   快速排序是從序列中選擇一個基準值,按照某種方式將該區間分成兩部分,基準

3664-順序表應用7:最大子段和之分治法-C語言

#include <stdio.h> #include <stdlib.h> int count=0; //定義全域性變數用來記錄遞迴次數 typedef struct{ int data[50010]; int length; }Lis

漢諾塔c語言實現()

     對於遞迴來講, 漢諾塔實際是經典到不能再經典的例子了,   每個資料結構的教材對會提到.      但是到最後只給出一段類似下面的一段程式碼: #include<stdio.h> void move(int n,char a,char b,cha

【經典問題】漢諾塔(C語言實現)

   這個月在學習Python,函式遞迴那一節提到了漢諾塔問題,這是一個很經典的問題,我們老師在之前也提到過這個例子,感覺蠻重要的,想記錄下來。為了向經典致敬,這篇就不用Python實現了,就用C語言~  漢諾塔的來歷我就不細說了,這裡就自行左擁度娘右抱谷歌腦補一下。請看下面

八皇后問題:解決/C語言(基礎方法)

/************************* *八皇后問題:遞迴解決/C語言 *按照8層8叉樹來想象,共有8^8種可能,對應每個葉子節點; *由根到葉子,自左至右遍歷每種情況; *剪枝掉不可行的方案; *及時輸出可行方案,繼續遍歷; *其間並未對每種可行方案累計儲存

全排列演算法(C++實現)

演算法實現思路 遞迴解決問題的方法就是將一個大問題不斷分解成小問題,直到小問題很容易解決為止 先看全排列怎麼分解成小問題:        假設要全排列“ABC”,先把A作為前部不變,全排列BC,同樣將B作為前部,全排列C,顯然是它本身 於是大問題變成了很容易解決的小問題了

整數劃分的非演算法C語言

記錄點滴成長: 整數劃分的非遞迴演算法 例如將整數6劃分為如下: 65 14 2 4 1 13 3 3 2 1 3 1 1 12 2 2 2 2 1 1 2 1 1 1 11 1 1 1 1 1如6有11個劃分。 #include "stdio.h"void  Div

【原始碼】將一個整數的每位數分解並按逆序放入一個數組中(用演算法)(C語言實現)

幫朋友做的,好像是一個面試題。如果僅僅是考察遞迴的話,應該是夠了,程式的健壯性和通用性都很一般的說…… #include <stdio.h> #include <stdlib.h&g

C語言演算法的學習

一、初識遞迴 程式呼叫自身的程式設計技巧稱為遞迴( recursion)。 一個過程或函式在其定義或說明中有直接或間接呼叫自身的一種方法,它通常把一個大型複雜的問題層層轉化為一個與原問題相似的規模較小的問題來求解,遞迴策略只需少量的程式就可描述出解題過程所需要的多次重複計算,大大地減少

資料結構實驗-C語言-二叉樹的建立,前、中、後序遍歷的遞迴演算法和非遞迴演算法,求葉子結點數目,求二叉樹深度,判斷二叉樹是否相似,求二叉樹左右子樹互換,二叉樹層序遍歷的演算法,判斷二叉樹是否是完全二叉樹

1.實驗目的 熟練掌握二叉樹的二叉連結串列儲存結構的C語言實現。掌握二叉樹的基本操作-前序、中序、後序遍歷二叉樹的三種方法。瞭解非遞迴遍歷過程中“棧”的作用和狀態,而且能靈活運用遍歷演算法實現二叉樹的其它操作。 2.實驗內容 (1)二叉樹的二叉連結串列的建立 (2)二叉樹的前、中、後

二叉樹中序遍歷(非)演算法實現--C語言

今天繼續二叉樹的學習。 昨天寫了一遍二叉樹的先序遍歷(非遞迴)演算法,今天寫一下二叉樹的二叉樹的中序遍歷(非遞迴)演算法。中序遍歷的非遞迴演算法有兩種,但是個人覺得只要掌握一種就可以了,只要自己的邏輯清晰,會哪一種又有什麼關係呢~ 首先給出今天的二叉樹的示例圖: 程式碼如下:

C++實現 演算法 - 賞金問題 - 整數因式分解

 使用遞迴方法實現以下問題  1.賞金問題     假設有四種面額的錢幣,1 元、2 元、5 元和 10 元,而您一共給我10元,     那您可以獎賞我1張10元,或10張1元,或5張1元外加1張5元等等。  

c語言演算法--深入淺出(1)

RECURSION EXERCISES 1 (遞迴練習1) 前言:資質駑鈍,剛剛學習遞迴的時候總是感覺有點空洞,懸乎。 可能沒有足夠例題練練手。最近找了幾道有難度層次的遞迴例題,在此分享給大家。 S

C語言漢諾塔--演算法

問題描述:   有一個梵塔,塔內有三個座A、B、C,A座上有諾幹個盤子,盤子大小不等,大的在下,小的在上(如圖)。 把這些個盤子從A座移到C座,中間可以借用B座但每次只能允許移動一個盤子,並且在移動過程中,3個座上的盤 子始終保持大盤在下,小盤在上。 描述簡化:把

C語言 二叉樹的遍歷 和(多種)非演算法

//二叉樹遍歷 //作者:nuaazdh //時間:2011年12月1日 #include<stdio.h> #include<stdlib.h> #define OK 1 #define ERROR 0 #defi