關於揹包問題的概念可以參考此處
給定乙個只包含正整數的非空陣列。是否可以將這個陣列分割成兩個子集,使得兩個子集的元素和相等。
示例 1: 輸入: [1, 5, 11, 5],輸出: true
解釋: 陣列可以分割成 [1, 5, 5] 和 [11].
示例 2:輸入: [1, 2, 3, 5],輸出: false
其實可以看成是乙個01揹包問題。能不能裝滿sum/2,能的話就返回true,否則返回false。
public boolean canpartition(int nums)
int sum = 0;
for (int num : nums)
if (sum % 2 != 0)
sum = sum / 2;
boolean res = new boolean[sum + 1];
res[0] = true;
for (int num : nums)
}return res[sum];
}
給定不同面額的硬幣 coins 和乙個總金額 amount。編寫乙個函式來計算可以湊成總金額所需的最少的硬幣個數。如果沒有任何一種硬幣組合能組成總金額,返回 -1。
示例 1:
輸入: coins = [1, 2, 5], amount = 11 輸出: 3 解釋: 11 = 5 + 5 + 1
示例 2: 輸入: coins = [2], amount = 3 輸出: -1
說明:你可以認為每種硬幣的數量是無限的。
可以看成是乙個完全揹包問題。用乙個完全揹包裝滿指定的金額
public int coinchange(int coins, int amount)
int dp = new int[amount + 1];
for (int coin : coins) else else }}
}}
return dp[amount] == 0 ? -1 : dp[amount];
}
給定不同面額的硬幣和乙個總金額。寫出函式來計算可以湊成總金額的硬幣組合數。假設每一種面額的硬幣有無限個。
示例 1: 輸入: amount = 5, coins = [1, 2, 5] 輸出: 4
解釋: 有四種方式可以湊成總金額:
5=55=2+2+1
5=2+1+1+1
5=1+1+1+1+1
示例 2: 輸入: amount = 3, coins = [2] 輸出: 0
解釋: 只用面額2的硬幣不能湊成總金額3。
因為每種面額是無限的,因此也是乙個完全揹包問題。
d 為動態規劃記錄陣列:
d[i] 代表,最多 i 元錢時可兌換的分配方案數量;
d[0] 時為初始條件,表示0元可以用0元兌換1次,所以 d[0] = 1。
d[i - c] 中,c 代表當前面值,d[i - c] 表示 i - c 元錢所有分配方案之和,d[i] 分配方案應該等於所有 d[i - c] 分配方案之和,這樣就可以快速的計算出 d[amount] 的和了。
public int change(int amount, int coins)
int dp = new int[amount + 1];
dp[0] = 1;
for (int coin : coins)
}return dp[amount];
}
給定乙個非空字串 s 和乙個包含非空單詞列表的字典 worddict,判定 s 是否可以被空格拆分為乙個或多個在字典中出現的單詞。
說明:拆分時可以重複使用字典中的單詞。
你可以假設字典中沒有重複的單詞。
示例 1:輸入: s = "leetcode", worddict = ["leet", "code"]
輸出: true
解釋: 返回 true 因為 "leetcode" 可以被拆分成 "leet code"。
示例 3:輸入: s = "catsandog", worddict = ["cats", "dog", "sand", "and", "cat"]
輸出: false
因為可以重複使用,所以這是乙個經典的完全揹包問題,dp[i]表示從0到i能否拆分。
狀態轉移方程為:dp[i] = s[j-->i] in worddict and dp[j]。
注意 :需要定義dp[0]為 true,因為如果字串本身就在 worddict 中,就不必看 dp 了,可以直接判斷為 true,因此 dp[0] = true;
public boolean wordbreak(string s, listworddict)
if (worddict == null || worddict.size() == 0)
setset = new hashset<>(worddict);
boolean dp = new boolean[s.length() + 1];
dp[0] = true;
for (int i = 1; i <= s.length(); i++) }}
return dp[s.length()];
}
給定乙個由正整數組成且不存在重複數字的陣列,找出和為給定目標正整數的組合的個數。
示例:nums = [1, 2, 3]target = 4 所有可能的組合為:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)
請注意,順序不同的序列被視作不同的組合。
因此輸出為 7。
此題的狀態轉移方程為dp[i] = dp[i-nums[0]]+dp[i-nums[1]]+...dp[i-nums[len-1]],條件為i>=nums[j];
dp[0] = 1,dp[0]表示組成0,乙個數都不選就可以了,所以dp[0]=1
舉個例子。假設nums=; target = 4
dp[4] = dp[4-1]+dp[4-2]+dp[4-3] = dp[3]+dp[2]+dp[1]
dp[1] = dp[0] = 1;
dp[2] = dp[1]+dp[0] = 2;
dp[3] = dp[2]+dp[1]+dp[0] = 4;
dp[4] = dp[4-1]+dp[4-2]+dp[4-3] = dp[3]+dp[2]+dp[1] = 7
**如下
public int combinationsum4(int nums, int target)
int dp = new int[target + 1];
//dp[0]表示組成0,乙個數都不選就可以了,所以dp[0]=1
dp[0] = 1;
for (int i = 1; i <= target; i++) }}
return dp[target];
}
01揹包演算法
核心 狀態轉換方程 01揹包問題 容量為10的揹包,有5種物品,每種物品只有乙個,其重量分別為5,4,3,2,1,其價值分別為1,2,3,4,5。設計演算法,實現揹包內物品價值最大。如下 輸出14 include include using namespace std int main int v ...
演算法 01揹包
揹包最大容量10,有以下5個商品及其價值,試求揹包所能容納的最大價值。序號1 2345 重量226 54價值6 3546 如下 include include define max v 100 using namespace std struct good 動態規劃求解 n 商品個數 m 揹包最大重...
01揹包演算法
01揹包問題 動態規劃的基本思想 動態規劃演算法可分解成從先到後的4個步驟 1.描述乙個最優解的結構,尋找子問題,對問題進行劃分。2.定義狀態。往往將和子問題相關的各個變數的一組取值定義為乙個狀態。某個狀態的值就是這個子問題的解 若有k個變數,一般用k維的陣列儲存各個狀態下的解,並可根 據這個陣列記...