文章目录
- 322.零钱兑换
-
- 279.完全平方数
-
- 139.单词拆分(二刷再看看!)
-
- 多重背包
-
- 背包问题总结
322.零钱兑换
- 题目链接:322. 零钱兑换
- 讲解链接:代码随想录
- 状态:一遍AC。
思路与重点
- 本题求钱币最小个数,那么钱币有顺序和没有顺序都可以,都不影响钱币的最小个数。所以本题的两个for循环内外层顺序也无所谓!
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
vector<int> dp(amount + 1, INT_MAX);
dp[0] = 0;
for(int i = 0; i < coins.size(); i++){
for(int j = coins[i]; j <= amount; j++){
if(dp[j - coins[i]] != INT_MAX) dp[j] = min(dp[j], dp[j - coins[i]] + 1);
}
}
return dp[amount] < INT_MAX ? dp[amount] : -1;
}
};
279.完全平方数
- 题目链接:279.完全平方数
- 讲解链接:代码随想录
- 状态:一遍AC。
思路与重点
class Solution {
public:
int change(int amount, vector<int>& coins) {
vector<unsigned long long> dp(amount + 1, 0);
dp[0] = 1;
for(int i = 0; i < coins.size(); i++){
for(int j = coins[i]; j <= amount; j++){
dp[j] += dp[j - coins[i]];
}
}
return dp[amount];
}
};
139.单词拆分(二刷再看看!)
- 题目链接:139.单词拆分
- 讲解链接:代码随想录
- 状态:没写出来。
思路与重点
- 用记忆化递归解决:使用memory数组保存每次计算的以startIndex起始的计算结果,如果memory[startIndex]里已经被赋值了,直接用memory[startIndex]的结果。
class Solution {
private:
bool backtracking (const string& s,
const unordered_set<string>& wordSet,
vector<bool>& memory,
int startIndex) {
if (startIndex >= s.size()) {
return true;
}
if (!memory[startIndex]) return memory[startIndex];
for (int i = startIndex; i < s.size(); i++) {
string word = s.substr(startIndex, i - startIndex + 1);
if (wordSet.find(word) != wordSet.end() && backtracking(s, wordSet, memory, i + 1)) {
return true;
}
}
memory[startIndex] = false;
return false;
}
public:
bool wordBreak(string s, vector<string>& wordDict) {
unordered_set<string> wordSet(wordDict.begin(), wordDict.end());
vector<bool> memory(s.size(), 1);
return backtracking(s, wordSet, memory, 0);
}
};
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
unordered_set<string> wordSet(wordDict.begin(), wordDict.end());
vector<bool> dp(s.size() + 1, false);
dp[0] = true;
for (int i = 1; i <= s.size(); i++) {
for (int j = 0; j < i; j++) {
string word = s.substr(j, i - j);
if (wordSet.find(word) != wordSet.end() && dp[j]) {
dp[i] = true;
}
}
}
return dp[s.size()];
}
};
多重背包
- 题目链接:56. 携带矿石资源
- 讲解链接:代码随想录
- 状态:直接看题解了。
思路与重点
- 多重背包和01背包是非常像的, 为什么和01背包像呢?每件物品最多有Mi件可用,把Mi件摊开,其实就是一个01背包问题了。
#include<iostream>
#include<vector>
using namespace std;
int main() {
int bagWeight,n;
cin >> bagWeight >> n;
vector<int> weight(n, 0);
vector<int> value(n, 0);
vector<int> nums(n, 0);
for (int i = 0; i < n; i++) cin >> weight[i];
for (int i = 0; i < n; i++) cin >> value[i];
for (int i = 0; i < n; i++) cin >> nums[i];
vector<int> dp(bagWeight + 1, 0);
for(int i = 0; i < n; i++) {
for(int j = bagWeight; j >= weight[i]; j--) {
for (int k = 1; k <= nums[i] && (j - k * weight[i]) >= 0; k++) {
dp[j] = max(dp[j], dp[j - k * weight[i]] + k * value[i]);
}
}
}
cout << dp[bagWeight] << endl;
}
背包问题总结