好比5 = 1+4 = 2+3 算法
問題2:有正整數 N, 可表示爲a1+a2+a3+...+aK=N;而且 0<a1<a2<...<aK; 求,一共有多少種表示法。.net
(在此,我自我檢討下:沒通過思考,起初想固然的認爲2和1有同樣的複雜度,簡直太弱了!)code
問題1的解法是利用遞歸回溯。關鍵在於定義一個f(n,k),其中n表示須要求的和,k表示容許的最大ai。此回溯算法的出口有兩個:一個是找到合適的序列;一個是子問題遍歷完成。遞歸
算法主要代碼以下:get
void f(int n, int k) { if (n == 0) { print_result(); count++; return ; } int max, min; max = (n<k)? n : (k); min = sqrt(2*n) - 1; min = (min < 1)?1:min; for (int i=max; i>=min; --i) { if ( !(n-i >= 0) ) continue; a[i] = 1; f(n-i, i-1); a[i] = 0; } }
初始調用是f(N, N-1) //計算和爲N的整數序列,ai最大不能超過N-1it
第二個問題使用動態規劃法,時間複雜度是N^2.class
主要思想是定義一個f[N+1][N+1],最後計算F[N][N-1].其中F[n][k]表示,和爲n,ai最大是k的序列數。遍歷
因而,就有im
F[n][k] = F[n][k-1] + F[n-k][k-1] (k < n)動態規劃
F[n][k] = F[n][n-1] + 1 (k>=n)
邊界條件F[0][0] = 1;
主要代碼以下:
for (int n=0; n<N+1; n++) for (int k=0; k<N+1; k++) { if (k==0) f[n][k] = 0; else if (k<n) f[n][k] = f[n][k-1] + f[n-k][k-1]; else if (k>=n) f[n][k] = f[n][n-1] + 1; else { printf("we should never get here!\n"); exit(-1); } }
因爲每一步的操做試試O(1)的加法,因此總的running time是O(N^2).
感謝OSC的幾位朋友, @zzz2012 @中山野鬼 @看能不能改個名 (哥們,打你的名字真不容易,我還特意查了下)
尤爲是@zzz2012
結束。
路漫漫其修遠兮,吾將上下而求索。