關鍵點:最後一個揹包的內的物品是哪個,最後一個物品有沒有進揹包。
揹包問題要將總承重放入狀態。
可行性揹包,計數型揹包,最值型揹包。
92. Backpack
在n個物品中挑選若干物品裝入揹包,最多能裝多滿?假設揹包的大小爲m,每個物品的大小爲A[i]
提示: 兩種思路,第一種狀態是f[i][w]表示能否用前i個物品拼出重量w。優化空間的的話,可以不在f中記錄i,然後從後向前遍歷 輸出第一個爲true的w的值。
第二種思路是直接記錄重量。
答案:
第一種
class Solution {
public:
/**
* @param m: An integer m denotes the size of a backpack
* @param A: Given n items with size A[i]
* @return: The maximum size
*/
int backPack(int m, vector<int> A) {
int n = A.size();
vector<vector<bool>> f(n + 1, vector<bool>(m + 1, false));
f[0][0] = true;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= m; j++) {
f[i][j] = f[i - 1][j];
if (j >= A[i-1] && f[i-1][j - A[i-1]]) {
f[i][j] = true;
}
} // for j
} // for i
for (int i = m; i >= 0; i--) {
if (f[n][i]) {
return i;
}
}
return 0;
}
};
class Solution {
public:
/**
* @param m: An integer m denotes the size of a backpack
* @param A: Given n items with size A[i]
* @return: The maximum size
*/
int backPack(int m, vector<int> A) {
vector<bool> f(m + 1, false);
f[0] = true;
for (int i = 0; i < A.size(); i++) {
for (int j = m; j >= A[i]; j--) {
f[j] = f[j] || f[j - A[i]];
}
}
for (int j = m; j >= 0; j--) {
if (f[j]) {
return j;
}
}
return 0;
}
};
第二種
public class Solution {
/**
* @param m: An integer m denotes the size of a backpack
* @param A: Given n items with size A[i]
* @return: The maximum size
*/
public int backPack(int m, int[] A) {
// write your code here
int f[] = new int[m + 1];
for (int i = 0; i < A.length; i++) {
for (int j = m; j >= A[i]; j--) {
f[j] = Math.max(f[j], f[j - A[i]] + A[i]);
}
}
return f[m];
}
}
563. Backpack V
給定N個正整數數組: A0, A1, ... , A n-1
一個正整數Target,求多少種組合加起來是Target,每個Ai只能用一次
提示:
答案:
public class Solution {
int backpackV(vector<int> A, int T){
int i, j;
int n = A.size();
if(n == 0) return 0;
vector<int> f(T + 1, 0);
f[0] = 1;
for(i = 1; i <= n; i++){
for(j = T; j >= 0; j--){
if(j >= A[i]){
f[j] = f[j - A[i]];
}
}
}
return f[T];
}
}
564. Backpack VI
給出一個都是正整數的數組 nums
,其中沒有重複的數。從中找出所有的和爲 target
的組合個數。一個數可以在組合中出現多次。數的順序不同則會被認爲是不同的組合。
提示:
答案:
class Solution {
public:
/**
* @param nums an integer array and all positive numbers, no duplicates
* @param target an integer
* @return an integer
*/
int backPackVI(vector<int>& nums, int target) {
// Write your code here
vector<int> dp(target + 1);
dp[0] = 1;
for (int i = 1; i <= target; ++i) {
for (auto a : nums)
if (i >= a) {
dp[i] += dp[i - a];
}
}
return dp.back();
}
};
125. Backpack II
有 n
個物品和一個大小爲 m
的揹包. 給定數組 A
表示每個物品的大小和數組 V
表示每個物品的價值.
問最多能裝入揹包的總價值是多大?
提示:
答案:
class Solution {
public:
/**
* @param m: An integer m denotes the size of a backpack
* @param A & V: Given n items with size A[i] and value V[i]
*/
int backPackII(int m, vector<int> A, vector<int> V) {
// write your code here
int f[m + 1];
for (int i = 0; i <=m ; ++i) f[i] = 0;
int n = A.size() , i, j;
for(i = 0; i < n; i++){
for(j = m; j >= A[i]; j--){
f[j] = max(f[j], f[j - A[i]] + V[i]);
}
}
return f[m];
}
};
440. Backpack III
給定N種物品,重量爲A[i],價值爲V[i],每種物品有無窮多個,揹包最大承重是正整數M,求能帶走的物品的最大價值。
提示:
優化之後將時間複雜度從O(M^2N)減少到O(MN),之後發現從左向右計算正好可以利用前面計算的新值與同列的老值,優化空間到O(N)。想對於揹包II只需改一行代碼,把從後往前改爲從前往後,這是一個巧合。
答案:
class Solution {
public:
/**
* @param m: An integer m denotes the size of a backpack
* @param A & V: Given n items with size A[i] and value V[i]
*/
int backPackIII(int m, vector<int> A, vector<int> V) {
// write your code here
int f[m + 1];
for (int i = 0; i <=m ; ++i) f[i] = 0;
int n = A.size() , i, j;
for(i = 0; i < n; i++){
for(j = A[i]; j <= m; j++){
f[j] = max(f[j], f[j - A[i]] + V[i]);
}
}
return f[m];
}
};