1. 程式人生 > >OpenJudge 簡單的整數劃分問題(遞迴)

OpenJudge 簡單的整數劃分問題(遞迴)

總時間限制: 
100ms 
記憶體限制: 
65536kB
描述

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

輸入
標準的輸入包含若干組測試資料。每組測試資料是一個整數N(0 < N <= 50)。
輸出
對於每組測試資料,輸出N的劃分數。
樣例輸入
5
樣例輸出
7
提示

5, 4+1, 3+2, 3+1+1, 2+2+1, 2+1+1+1, 1+1+1+1+1

思路:

根據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,因此這情況下
          為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);
      綜上所述:
                             f(n, m)=   1;                    (n=1 or m=1)
                            f(n,m)   =    f(n, n);         (n<m)
                             1+ f(n, m-1);                  (n=m)
                             f(n-m,m)+f(n,m-1);        (n>m)

程式碼:

#include<iostream>
using namespace std;

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

int main() {
	int n;
	while(cin>>n) {
		cout<<sp(n,n)<<endl;
	}
	return 0;
}