動態規劃 數字和為sum的方法數

2021-08-21 18:30:39 字數 2188 閱讀 2268

問題描述:

給定乙個有n個正整數的陣列a和乙個整數sum,求選擇陣列a中部分數字和為sum的方案數。

當兩種選取方案有乙個數字的下標不一樣,我們就認為是不同的組成方案。

輸入描述:

輸入為兩行: 第一行為兩個正整數n(1 ≤ n ≤ 1000),sum(1 ≤ sum ≤ 1000)第二行為n個正整數a[i](32位整數),以空格隔開。

輸出描述:

輸出所求的方案數

示例1輸入

5 15

5 5 10 2 3

輸出

這道題是一道動態規劃的揹包,我們以上面的輸入輸出為例

首先,將輸入的資料放到乙個一維陣列裡,我這裡使用的是vector,都一樣

注意: 下標為0的位置跳過,這個位置預設值為0,我們的資料從下標為1的位置開始

下標v[i]

接下來我們構建乙個二維陣列,由於這個題目給出的n,sum的範圍都是 1000,於是我們構建乙個 1001*1001的二維陣列dp

注意: 這個陣列不要構建在棧上,這個空間可能很大,這裡要求的是1000,有的題目會要求5000,難道要在棧上構建乙個 5001*5001*sizeof(int) 大小的空間嗎

所以這裡建議將這個陣列定義在全域性區或者在對上動態開闢,不過我覺得在全域性區上使用起來比較簡單

p[i]

舉乙個例子:

比如圖中黃色的點,他的座標為 (2,2), 表示的意思為我們現在擁有質量為 v[0](也就是0)的物品和質量為v[1](也就是5)的物品 (注意,這裡只要小於等於當前行的物品我們都可以看作是擁有的),我們需要組合成乙個質量為5(也就是當前列的下標)的揹包,黃色格仔處填的就是方法數

p[i]

我們可以理解為

p[i]

可以理解為

迴圈條件:

for(int i = 1; i <= n; ++i)

}

情況一: 新增物品的質量(v[i]) 大於所需要合成揹包的質量 j

這時候揹包已經裝不下新的物品了,所以可裝的物品應該不變,即繼承了上一行的值即可    ->    dp[i][j] = dp[i-1][j]

情況二: 新增的物品質量小於等於需要合成揹包的質量 j

先給出結論: dp[i][j] =  dp[i-1][j] + dp[i-1][j- p[i] ]

我們以第二行為例:

這一行我們新增的物品質量為 5(p[1])

所有 j < 5 的列 (紫色) ,我們都不可以將 5再次加到揹包中,於是就繼承上一行的值

所有 j >= 5的列 (黃色), 都有可能和之前有過的物品組合成當前的列值, 比如: 座標為[1][5]這乙個格仔(亮黃色),我們新增了乙個質量為5的物品,之前有乙個質量為0的物品,組合起來就可以構成乙個質量為5的揹包 

p[i]

上面情況二的例子不夠明顯,這次我們以座標為 [5][10]舉例;

當前我們所擁有的物品質量: 0,5,5,10,2,3

我們所要合成的揹包質量: 10

假設我們已經知道當我們只有 0,5,5,10,2的物品時,有兩種合成方法(即當前行的上一行)

當我們新增了乙個質量為3的物品時,只要知道了之前有多少種組合可以構成質量為7的揹包

現在可構成質量為10 的揹包的方法數 = 上一行構成10的值 + 上一行構成7的值

即: 2 + 2 =  4種

p[i]

這道題我們所要求解的是和為sum的方法數,即找 [n][sum] 這一點對應的值即可

#include using namespace std;

#include #include #include int dp[1001][1001];

int digit_sum(int n,int sum,vector& v)

// 2. dp第一行全部賦值為0

for(int j = 1; j <= sum; ++j)

// 3. 根據上一行的值算出當前位置的值

for(int i = 1; i <= n; ++i)

else}}

return dp[n][sum];

}int main()

int res = digit_sum(n,sum,v);

cout

}

動態規劃 數字和為sum的方法數

題目描述 給定乙個有n個正整數的陣列a和乙個整數sum,求選擇陣列a中部分數字和為sum的方案數。當兩種選取方案有乙個數字的下標不一樣,我們就認為是不同的組成方案。輸入描述 輸入為兩行 第一行為兩個正整數n 1 n 1000 sum 1 sum 1000 第二行為n個正整數a i 以空格隔開。輸出描...

數字和為sum的方法數

給定乙個有n個正整數的陣列a和乙個整數sum,求選擇陣列a中部分數字和為sum的方案數。當兩種選取方案有乙個數字的下標不一樣,我們就認為是不同的組成方案。輸入描述 輸入為兩行 第一行為兩個正整數n 1 n 1000 sum 1 sum 1000 第二行為n個正整數ai,以空格隔開。輸出描述 輸出所求...

求解數字和為 sum 的方法數問題

問題描述 給定乙個有 n 個正整數的陣列 a 和乙個整數 sum,求選擇陣列 a 中部分數字和為 sum 的方案數。若兩種選區方案有乙個數字的下標不一樣,則認為是不同的方案。輸入描述 輸入為兩行,第 1 行為兩個正整數 n sum,第 2 行為 n 何正整數 a i 以空格 隔開。輸出描述 輸出所求...