1. 程式人生 > >【動態規劃/揹包】整數劃分的5種情況

【動態規劃/揹包】整數劃分的5種情況

1.將n劃分成若干正整數之和的劃分數(可以存在相同整數)。

轉移方程如下:

dp[n][m]=dp[n][m-1]+ dp[n-m][m]  dp[n][m]表示整數 n 的劃分中,每個數不大於 m 的劃分數。

理解①:

根據劃分中包不包含m的情況分為2種,一種情況是劃分中包含m,則剩下數的總和剩下n-m,相當於其劃分數為dp[n-m][m]。另一種情況是劃分中不包含m,那麼其劃分數為dp[n][m-1]。

程式碼:

        dp[0][0]=1;  
        for (int i=0;i<=n;i++)  
        {  
            for (int j=1;j<=n;j++)  
            {  
                j<=i?dp[i][j]=dp[i-j][j]+dp[i][j-1]: dp[i][j]=dp[i][i];  
            }  
        }
       cout<<dp[n][n];

理解②:

也可以看成完全揹包問題,有1到n個揹包,第i個揹包的重量為i,價值為i。dp[j] 是用前 i 個數能構成 j 的種類數

程式碼:

dp[0] = 1;
for (i = 1;i <= N;i++)
  for (j = i;j <= N;j++)
     dp[j] += dp[j-i];

2、將n劃分成若干不同正整數之和的劃分數(不可以存在相同整數)

轉移方程如下:

dp[n][m]=dp[n][m-1]+ dp[n-m][m-1]   dp[n][m]表示整數 n 的劃分中,每個數不大於 m 的劃分數。

理解①:

根據劃分中包不包含m的情況分為2種,一種情況是劃分中包含m,則剩下數的總和剩下n-m,相當於其劃分數為dp[n-m][m-1]。(跟1的情況的區別就在這裡,因為不能重複,所以應該是m-1)另一種情況是劃分中不包含m,那麼其劃分數為dp[n][m-1]。

程式碼:

dp[0][0]=1;  
        for (int i=0;i<=n;i++)  
        {  
              for (int j=1;j<=n;j++)  
              {  
                   j<=i?dp[i][j]=dp[i-j][j-1]+dp[i][j-1]: dp[i][j]=dp[i][i];  
              }  
        }  
cout<<dp[n][n];

理解②:

由於每個數最多隻能取1次,是經典的01揹包,程式碼如下

程式碼:

 dp[0]= 1;
 for(i = 1;i <=n ;i++)
   for(j = n;j >= i ;j--)
    dp[j] += dp[j-i];
 

3、將n劃分為k個數的劃分數。

轉移方程

dp[n][k]= dp[n-k][k]+ dp[n-1][k-1];

理解

根據劃分中包不包含1的情況分為2種,如果不包含1,即所有數都大於等於2,我們可以取出n個1分到每一份(總共k份)上去,再將剩下的n-k個1分成k份,總共有dp[n-k][k]種分法。如果包含1,我們把那份單獨的1取出來,總和就剩下n-1,數也剩下k-1個,即有dp[n-1][k-1]種分法。

程式碼:

for(int i=1;i<=n;i++)  
        for (int j=1;j<=i;j++)  
        {  
              if(j==1)  
              dp[i][j]=1;  
              else  
              dp[i][j]=dp[i-j][j]+dp[i-1][j-1];   
        }  

4、將n分成最大數不超過k的劃分數

       轉移及思路同1,方程最後的輸出為dp[n][k];如果看成揹包問題,即是用前k個揹包來裝結果,將第一層迴圈改為i<=k即可。

5、將n劃分為若干奇數的方法

轉移方程

 g[i][j] =f[i - j][j];f[i][j] = f[i - 1][j - 1] + g[i - j][j];g[i][j]:將i劃分為j個偶數;f[i][j]:將i劃分為j個奇數

思路

對於g[i][j]= f[i- j][j],從i中拿出j個1到每一份中,則剩下的數總和為i-j也必須為奇數,i-j分成j個奇數,所以劃分數為f[i-j][j]。

對於f[i][j] = f[i- 1][j - 1] + g[i - j][j],如果不包含1,每份都大於等於2,將j個1拿出來分到每一份中,剩下的i-j必須劃分為j份偶數,即g[i-j][j]。如果包含1,將那份1拿出來,剩餘的i-1分成j-1個奇數,即f[i-1][j-1]。

程式碼:

for(int i=0;i<=n;i++)  
       {  
           dp[i][1]=1;  
           if(i&1)  
           dp[0][i]=1;  
        }  
        for (int i=1;i<=n;i++)  
        {  
            for (int j=1;j<=n;j++)  
            {  
                if(j&1)  //相當於上面思路中的f[i][j]
                {  
                    if(j<=i)  
                    dp[i][j]=dp[i-j][j]+dp[i][j-1];  
                    else   
                    dp[i][j]=dp[i][i];  
                }  
                else  //相當於上面思路中的g[i][j]
                dp[i][j]=dp[i][j-1];  
            }  
        }  

揹包思路

因為只能是奇數,所以偶數的揹包種類(i=2,4,6,8……)不符合要求,i++改為i+=2即可

程式碼:

dp[0] = 1;
for (i = 1;i <= N;i+=2)
   for (j = i;j <= N;j++)
     dp[j] += dp[j-i];

相關推薦

動態規劃/揹包整數劃分5情況

1.將n劃分成若干正整數之和的劃分數(可以存在相同整數)。 轉移方程如下: dp[n][m]=dp[n][m-1]+ dp[n-m][m]  dp[n][m]表示整數 n 的劃分中,每個數不大於 m

NOJ1540動態規劃_DP最長遞增子序列的長度

1540.最長遞增子序列的長度 時限:1000ms 記憶體限制:10000K  總時限:3000ms 描述 給定一個序列,求它的最長遞增子序列的長度 輸入 先輸入一個正整數n,表示序列的長度,再輸入n個整數表示這個序列 輸出 輸出它的最長遞增子序列的長

程式設計網格無水題動態規劃最大字串和

Written By MorrowWind,csdnicewing 可以到洛谷的P115上去練習  https://www.luogu.org/problemnew/show/P1115 題目描述         給出資料個

Apple Catching動態規劃-dp

Apple Catching It is a little known fact that cows love apples. Farmer John has two apple trees (which are conveniently numbered 1 and

HDU 1159.Common Subsequence動態規劃DP3月8

Common Subsequence Problem Description A subsequence of a given sequence is the given sequence with some elements (possible none) lef

白話演算法之動態規劃入門

好了,讓我們從最小的i開始吧。當i=0,即我們需要多少個硬幣來湊夠0元。由於1,3,5都大於0,即沒有比0小的幣值,因此湊夠0元我們最少需要0個硬幣。 (這個分析很傻是不是?彆著急,這個思路有利於我們理清動態規劃究竟在做些什麼。) 這時候我們發現用一個標記來表示這句“湊夠0元我們最少需要0個硬幣。”會比較方便

動態規劃22LiberOJ#515. 「LibreOJ β Round #2」貪心只能過樣例(bitset優化)

題目描述 一共有 n個數,第 i 個數 xi 可以取 [ai,bi] 中任意值。 設 S=∑xi2​​​,求 S 種類數。 輸入輸出格式 第一行一個數 n。 然後 n 行,每行兩個數表示 ai,bi​​。 輸出一行一個

動態規劃問題編程題

clas nal spa 規劃 title can ice https rmi 題目來源牛客網 https://www.nowcoder.com/practice/1177e9bd1b5e4e00bd39ca4ea9e4e216?tpId=90&&tqId=

動態規劃-硬幣找零問題四情況

題目1:給定陣列arr,arr中所有的值都是正數且不重複。每個值代表一種面值的貨幣,每種面值的貨幣可以使用任意張,再給定一個整數aim代表要找的錢數,求組成aim的最少貨幣數。 舉例:  arr[5,2,3],aim=20。  4張5元可以組成20元,其他的找錢方案都要使

DP_動態規劃整數劃分

題目連結:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=90 整數劃分 時間限制:3000 ms  |  記憶體限制:65535 KB 難度:3 輸入 第一行是測試資料的數目M(1&

POJ-2184 Cow Exhibition 動態規劃DP+01揹包變換

題目傳送門 題目:共有N頭牛,接下來N行是每頭牛的智商和情商,從這些牛中任意選取若干頭牛,使得牛的智商和+情商和最大,同時智商和(TS),情商和(TF)都不小於0。 題解:以智商作為容量,求前i頭牛在智商為j的情況下的最大情商 。因為有負數,所以容量擴大100000,修改dp陣

HDU-2844 Coins 動態規劃DP+多重揹包

題目傳送門 題目:有n種硬幣,第i種硬幣的價值為Ai,數目為Ci,求這些硬幣能配出1~m中的幾種價值。 題解:dp[j]表示是否能配出價值j。sum[i][j]表示第i種硬幣取到價值j時需要的數目。sum陣列可以壓掉i的那一維,每次都要記得清零。 AC程式碼: #include

POJ-2392 Space Elevator 動態規劃DP+多重揹包

題目傳送門 題目:牛要去太空了!他們計劃通過建造一種太空升降機來達到軌道:一個巨大的積木塔。他們有K (1 <= K <= 400)不同型別的積木來建造塔。型別i的每個塊的高度都是h_i (1 <= h_i <= 100),並且數量上都是c_i (1 <= c_

LeetCode-動態規劃-單詞劃分

給定一個非空字串 s 和一個包含非空單詞列表的字典 wordDict,判定 s 是否可以被空格拆分為一個或多個在字典中出現的單詞。 說明: 拆分時可以重複使用字典中的單詞。 你可以假設字典中沒有重

51nod1085 揹包問題動態規劃

在N件物品取出若干件放在容量為W的揹包裡,每件物品的體積為W1,W2……Wn(Wi為整數),與之相對應的價值為P1,P2……Pn(Pi為整數)。求揹包能夠容納的最大價值。 Input 第1行,2個整數,N和W中間用空格隔開。N為物品的數量,W為揹包的容量。(1 <=

動態規劃--01揹包問題

o1揹包問題:一個揹包體積為V, 現有n個物品,第i個物品體積為w[i],價值為c[i]。問在不超出揹包 容量前提下,揹包 最多能裝下多少價值的物品。 之所以叫01揹包是因為這類題都可以歸結為第i個物品 放還是不放問題。這裡用二維陣列表示(當然也可用一維) 若第i個物品放

動態規劃分組揹包

問題: 有N件物品,告訴你這N件物品的重量以及價值,將這些物品劃分為K組,每組中的物品互相沖突,最多選一件,求解將哪些物品裝入揹包可使這些物品的費用綜合不超過揹包的容量,且價值總和最大。 演算法: 首先判斷一個分組當中的一件物品,同01揹包一樣,此物品存在兩種狀態,

經典動態規劃問題0-1揹包問題

0,1揹包問題 一個揹包有一定的承重cap,有N件物品,每件都有自己的價值,記錄在陣列v中,也都有自己的重量,記錄在陣列w中,每件物品只能選擇要裝入揹包還是不裝入揹包,要求在不超過揹包承重的前提下,選出物品的總價值最大。 每個物品只有1個,給定物品的重量w價值v及物品數n和承重cap。請返回

動態規劃常見揹包問題合集

01揹包:  有N件物品和一個容量為V的揹包。(每件物品只有一件)第i件物品的費用是c[i],價值是v[i],求解將哪些物品裝入揹包使總價值最大。 轉移方程:f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]},可以優化只用一維陣列. 程式碼