一、01背包
416. 分割等和子集
力扣
class Solution {
public:
bool canPartition(vector<int>& nums) {
int sum = 0;
int size = nums.size();
for (int i = 0; i < size; ++i) {
sum += nums[i];
}
if (sum % 2 == 1) {
return false;
}
int target = sum / 2;
vector<vector<int>> dp(size + 1, vector<int>(target + 1, 0));
if (nums[0] <= target) {
dp[0][nums[0]] = 1;
}
for (int i = 1; i < size; ++i) {
for (int j = 1; j <= target; ++j) {
if (j > nums[i]) {
dp[i][j] = dp[i - 1][j - nums[i]] | dp[i - 1][j];
}
else {
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[size - 1][target];
}
};
二、完全背包
322. 零钱兑换
力扣
还没做完,用该法C++超时,需继续看其他二维数组的算法
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
// https://www.cnblogs.com/yxym2016/p/12758327.html
// https://www.iteye.com/blog/yangliuy-1469399
int n=coins.size();
int INF=9999;
vector<vector<int>> dp(n + 1, vector<int>(amount + 1, 0));
//初始化,amount=0
for (int i = 1; i <= n ; i++) {
dp[i][0]=0;
}
//初始化,coins=0
for (int i = 1; i <= amount; i++) {
dp[0][i]=INF;
}
for (int i = 1; i <=n ; i++) {
for (int j = 1; j <=amount ; j++) {
//******************* 写法1 start
dp[i][j] = dp[i-1][j]; //赋值的目的,dp[i][j]最烂的结果是dp[i - 1][j],一会用这个结果到for循环中去和不同的k下的dp[i][j]比,取个for循环中的最小值
for (int k = 1; k <= j /coins[i - 1] ; k++) {
if(dp[i-1][j-k*coins[i-1]]!=INF){
dp[i][j] = min(dp[i][j], dp[i - 1][j - k* coins[i - 1]] + k);
}
}
//***************** 写法1 end
//这里有一个问题:写法2是有问题的,问题在哪里?
/** 写法2 start
* for (int k = 1; k*coins[i-1]<=j ; k++) {
* if(dp[i-1][j-k*coins[i-1]]!=INF){
* dp[i][j]=Math.min(dp[i-1][j-k*coins[i-1]]+k,dp[i-1][j]);
* }
* }
* 写法2 end
*/
}
}
return dp[n][amount]==INF?-1:dp[n][amount];
}
};