多重部分和問題 動態規劃

2021-10-07 09:30:12 字數 1771 閱讀 8059

這個問題可以用動態規劃求解,不過如何定義遞推關係會影響最終的複雜度。

定義:dp[i+1][j]:=用前i中數字是否能加和成j。 (能加成則為1,不能為0)

(1)能加成數字j,那麼第i個數字可能需要k個(k=0、1、…、m[i])dp[i][j]=dp[i][j-k*a[i]]=1;

(2)不能加成數字j.dp[i][j]=0

#include

#include

#include

#include

using

namespace std;

int a[

500]

,m[500];

bool dp[

500]

[500];

intmain()

///初始化邊界

fill

(dp[0]

,dp[0]

+500

*500,0

);dp[0]

[0]=

true

;///表示沒有選任何數字,所有加和為0

for(

int i=

0;i}if

(dp[n]

[k]) cout<<

"yes"

"no"

}

定義遞推式:dp[i+1][j]:用前i種數加和得到j時,第i種數最多能剩多少個(不能加和得到j的情況為-1)

如果前i-1個數加和能得到j的話,第i個數就剩餘m[i]個。此外,前i種數加和得出j-a[i]時第i種數還剩下k(k>0)的話,用這i種數加和得到j時第i種數剩k-1個。

if

(dp[i]

[j]>=

0) dp[i+1]

[j]=m[i]

else

if(j||dp[j+1]

[j-a[i]

]<=

0) dp[i+1]

[j]=-1

;else dp[i+1]

[j]=dp[i+1]

[j-a[i]]-

1;

#include

#include

#include

#include

using

namespace std;

int a[

500]

,m[500];

bool dp[

500]

[500];

intmain()

///dp[i+1][j]:用前i種數加和得到j時,第i種數最多能剩多少個(不能加和得到j的情況為-1)

///初始化邊界,dp[i][j]=-1不能加和得到i;

fill

(dp[0]

,dp[0]

+500

*500,-

1); dp[0]

[0]=

0;for(

int i=

0;i)else

if(j||dp[i+1]

[j-a[i]

]<=0)

else}}

if(dp[n]

[k]>=

0) cout<<

"yes"

"no"

}

多重部分和問題(動態規劃)

問題描述 有n中不同大小的數字ai,每種mi個。判斷是否可以從這些數字之中選出若干個使它們的和恰好為k 限制條件 1 n 100 1 ai,mi,100000 1 k 100000 定義bool dp i 1 j 前i個數 含 能否加和為 j for int k 0 k a i j k m i k ...

多重部分和問題

有 n 種物品,第i種物品的每個物品的價值是 ai 數目是 mi 判斷是否可以選擇若干數字使得價值和是k。1 n 100 1 ai,m i,10 5 1 k 105 看作揹包大小是k,物品的價值和體積都是ai 物品數目是 mi 的多重揹包。如果最大價值是 k 的話就是可以選出,否則便是不能選出。利用...

多重部分和問題

有n種不同大小的數字a i 每種各m i 個。判斷是否可以從這些數字之中選出若干使它們的和恰好為k。dp i 表示以a i 為末尾的最長上公升子串行的長度。include include include includeusing namespace std define maxn 10010 int...