算法設計--整數劃分問題

整數劃分問題:
將正整數n表示成一系列正整數之和:n=n1+n2+…+nk,其中n1≥n2≥…≥nk≥1,k≥1。正整數n的這種表示稱爲正整數n的劃分。求正整數n的不同劃分個數。

算法分析:
根據n和m的關係,可以考慮下面幾種情況:
(1)當n = 1時,不管m的值爲多少(m > 0),只有一種劃分即 { 1 }。
(2)當m = 1 時,不管n的值爲多少,只有一種劃分即n個1,{1,1,1,1…..1}。
(3)當n = m 時,根據劃分中是否包含n,可以劃分兩種情況:
(a)劃分中包含n的情況,只有一個,即{ n }。
(b)劃分中不包含n的情況,這時候劃分中最大的數字也一定比n小,及n的所有n-1劃分,因此可以用遞歸來解決f(n,n) = f(n,n-1)+1.
(4)當n < m 時,由於劃分中不可能出現負數,(n最多也就是n個1,因此不可能出現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).
綜合以上情況,可以看出,整數劃分具有遞歸定義的特徵,其遞歸表達式爲:
這裏寫圖片描述

算法實現

// test01_huafen.cpp : 定義控制檯應用程序的入口點。
//
#include "stdafx.h"
int q(int n,int m)
{
    if ((n<1)||(m<1))  return 0;
    if ((n==1)||(m==1))  return 1;
    if (n<m) return q(n,n);
    if (n==m) return q(n,m-1)+1;
        return q(n,m-1)+q(n-m,m);
}
int _tmain(int argc, _TCHAR* argv[])
{
    int n;
    printf("輸入一個整數:");
    scanf("%d",&n);
    printf("%d",q(n,n));
    scanf("%d",n);
    return 0;
}

結果:

輸入一個整數:6
11
將輸入的數據進行檢驗:
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;
如上圖劃分所示,總共有11中不同的劃分結果。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章