日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

NYOJ90 整数划分(经典递归和dp)

發(fā)布時(shí)間:2023/12/2 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 NYOJ90 整数划分(经典递归和dp) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

整數(shù)劃分

時(shí)間限制:3000?ms ?|? 內(nèi)存限制:65535?KB 難度:3 描述
將正整數(shù)n表示成一系列正整數(shù)之和:n=n1+n2+…+nk,?
其中n1≥n2≥…≥nk≥1,k≥1。?
正整數(shù)n的這種表示稱為正整數(shù)n的劃分。求正整數(shù)n的不?
同劃分個(gè)數(shù)。?
例如正整數(shù)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。?

輸入
第一行是測試數(shù)據(jù)的數(shù)目M(1<=M<=10)。以下每行均包含一個(gè)整數(shù)n(1<=n<=10)。
輸出
輸出每組測試數(shù)據(jù)有多少種分法。
樣例輸入
1 6
樣例輸出
11
來源
[苗棟棟]原創(chuàng)

思路:

遞歸法:

整數(shù)劃分問題是算法中的一個(gè)經(jīng)典命題之一,有關(guān)這個(gè)問題的講述在講解到遞歸時(shí)基本都將涉及。所謂整數(shù)劃分,是指把一個(gè)正整數(shù)n寫成如下形式:
? ? ? ?n=m1+m2+...+mi; (其中mi為正整數(shù),并且1 <= mi <= n),則{m1,m2,...,mi}為n的一個(gè)劃分。
? ? ? ?如果{m1,m2,...,mi}中的最大值不超過m,即max(m1,m2,...,mi)<=m,則稱它屬于n的一個(gè)m劃分。這里我們記n的m劃分的個(gè)數(shù)為f(n,m);
? ? ? ?例如但n=4時(shí),他有5個(gè)劃分,{4},{3,1},{2,2},{2,1,1},{1,1,1,1};
? ? ? ?注意4=1+3 和 4=3+1被認(rèn)為是同一個(gè)劃分。
? ? ? ?該問題是求出n的所有劃分個(gè)數(shù),即f(n, n)。下面我們考慮求f(n,m)的方法;
? ? ? ?根據(jù)n和m的關(guān)系,考慮以下幾種情況:?
? ? ? ?(1)當(dāng) n = 1 時(shí),不論m的值為多少(m > 0 ),只有一種劃分即 { 1 };
? ? ? ? (2) ?當(dāng) m = 1 時(shí),不論n的值為多少,只有一種劃分即 n 個(gè) 1,{ 1, 1, 1, ..., 1 };
? ? ? ? (3) ?當(dāng) n = m 時(shí),根據(jù)劃分中是否包含 n,可以分為兩種情況:
? ? ? ? ? ? ? (a). 劃分中包含n的情況,只有一個(gè)即 { n };
? ? ? ? ? ? ? (b). 劃分中不包含n的情況,這時(shí)劃分中最大的數(shù)字也一定比 n 小,即 n 的所有 ( n - 1 ) 劃分。
? ? ? ? ? ? ? 因此 f(n, n) = 1 + f(n, n-1);
? ? ? ? (4) 當(dāng) n < m 時(shí),由于劃分中不可能出現(xiàn)負(fù)數(shù),因此就相當(dāng)于 f(n, n);
? ? ? ? (5) 但 n > m 時(shí),根據(jù)劃分中是否包含最大值 m,可以分為兩種情況:
? ? ? ? ? ? ? ?(a). 劃分中包含 m 的情況,即 { m, { x1, x2, ..., xi } }, 其中 { x1, x2, ..., xi } 的和為 n - m,可能再次出現(xiàn) m,因此是(n - m)的 m 劃分,因此這種劃分
? ? ? ? ? ? ? ? ? ? ?個(gè)數(shù)為 f(n-m, m);
? ? ? ? ? ? ? ?(b). 劃分中不包含 m 的情況,則劃分中所有值都比 m 小,即 n 的 ( m - 1 ) 劃分,個(gè)數(shù)為 f(n, m - 1);
? ? ? ? ? ? ? 因此 f(n, m) = f(n - m, m) + f(n, m - 1);
? ? ? ? ?綜合以上情況,我們可以看出,上面的結(jié)論具有遞歸定義特征,其中(1)和(2)屬于回歸條件,(3)和(4)屬于特殊情況,將會(huì)轉(zhuǎn)換為情況(5)。而情況(5)為通用情況,屬于遞推的方法,其本質(zhì)主要是通過減小m以達(dá)到回歸條件,從而解決問題。其遞推表達(dá)式如下:

? ? ? ? ?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 )

以上講解來自于:http://www.cnblogs.com/hoodlum1980/archive/2008/10/11/1308493.html

看了這個(gè),代碼就很簡單了

動(dòng)態(tài)規(guī)劃法:

數(shù)組dp[N][M]表示N為被劃分?jǐn)?shù),M為劃分?jǐn)?shù)的最大值,此題M==N,故即求dp[N][N];
1>狀態(tài)轉(zhuǎn)移方程:


dp[N][M]=dp[N][M-1]+dp[N-M][M];


該怎樣理解呢?這里分兩步:


Step 1:所劃分的最大數(shù)不包括M,即每個(gè)劃分?jǐn)?shù)都是小于M的,此時(shí)總數(shù)為dp[N][M-1].


Step 2:所劃分的最大數(shù)包括M,那么這一步被劃分?jǐn)?shù)就應(yīng)該減去一個(gè)M,此時(shí)總數(shù)為dp[N-M][M].


到這里就是完整的思路了,應(yīng)該注意的是上面的劃分,劃分?jǐn)?shù)里有重復(fù)的數(shù),那么如果要求劃分?jǐn)?shù)沒有重復(fù)的呢,該怎樣求呢?


這里的狀態(tài)轉(zhuǎn)移方程和上面就有點(diǎn)細(xì)微區(qū)別了.先來看看方程:
2>dp[N][M]=dp[N][M-1]+dp[N-M][M-1];


其實(shí)聯(lián)系1中的步驟就不難理解了,同樣分為兩步:


Step 1:所劃分的最大數(shù)不包括M,即每個(gè)劃分?jǐn)?shù)都是小于M的,此時(shí)總數(shù)也是dp[N][M-1].


Step 2:所劃分的最大數(shù)包括M,那么劃分就的相應(yīng)的減去M,注意到不能重復(fù),即M劃分?jǐn)?shù)出現(xiàn)的次數(shù)只能為1.所以M就得換成M-1了,即dp[N-M][M-1].


3>在拓展一下,要是劃分的個(gè)數(shù)為確定的數(shù)呢?即dp[N][K].表示N被劃分成K個(gè)數(shù).


這時(shí)狀態(tài)轉(zhuǎn)移方程就為


dp[N][K]=dp[N-K][K]+dp[N-1][K-1].


應(yīng)該這樣理解:
Step 1:被劃分的K個(gè)數(shù)中不包括1,那么就應(yīng)該先自動(dòng)的為其分配1,K個(gè)數(shù)共N-K,剩下的數(shù)自由分配,總能保證其值大于2,即dp[N-K][K].


Step 2:存在一個(gè)數(shù)為1的情況,此時(shí)剩下的N-1分給K-1個(gè)數(shù),即dp[N-1][K-1].

來源:http://www.cnblogs.com/xl1027515989/p/3603533.html

代碼1(遞歸):

#include <cstdio> #include <cstring> #include <string> #include <set> #include <iostream> #include <cmath> #include <stack> #include <queue> #include <vector> #include <algorithm> #define mem(a,b) memset(a,b,sizeof(a)) #define inf 0x3f3f3f3f #define mod 10000007 #define debug() puts("what the fuck!!!") #define ll long long using namespace std; int f(int n,int m)//f(n,m)定義的是n的m劃分,m是能組成n的數(shù)中的最大值 {if(n==1||m==1) return 1;if(n==m) return f(n,n-1)+1;if(n<m) return f(n,n);if(n>m) return f(n-m,m)+f(n,m-1); } int main() {int t,n;scanf("%d",&t);while(t--){scanf("%d",&n);printf("%d\n",f(n,n));}return 0; } View Code

?

代碼2(DP):

#include <cstdio> #include <cstring> #include <string> #include <set> #include <iostream> #include <cmath> #include <stack> #include <queue> #include <vector> #include <algorithm> #define mem(a,b) memset(a,b,sizeof(a)) #define inf 0x3f3f3f3f #define mod 10000007 #define debug() puts("what the fuck!!!") #define ll long long using namespace std; int dp[15][15];//dp[n][m],n為被劃分?jǐn)?shù),m為劃分?jǐn)?shù)中的最大值 int main() {int t,n;scanf("%d",&t);while(t--){mem(dp,0);scanf("%d",&n);for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(i==j)dp[i][j]=dp[i][j-1]+1;else if(i<j)dp[i][j]=dp[i][i];else if(i>j)dp[i][j]=dp[i-j][j]+dp[i][j-1];}}printf("%d\n",dp[n][n]);}return 0; } View Code

?

轉(zhuǎn)載于:https://www.cnblogs.com/Roni-i/p/8614919.html

總結(jié)

以上是生活随笔為你收集整理的NYOJ90 整数划分(经典递归和dp)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。