一、题目打卡
1.1 二维背包问题
题目链接:46. 携带研究材料(第六期模拟笔试)
#include<iostream>
#include<vector>
using namespace std;int n, bagweight;// bagweight代表行李箱空间
void solve() {vector<int> weight(n, 0); // 存储每件物品所占空间vector<int> value(n, 0); // 存储每件物品价值for(int i = 0; i < n; ++i) {cin >> weight[i];}for(int j = 0; j < n; ++j) {cin >> value[j];}// 一开始就初始化为0,第一列就不用考虑了vector<vector<int>> dp(n,vector<int>(bagweight + 1,0));// 第一行的初始化要从满足重量要求的位置开始初始化for(int i = weight[0]; i <= bagweight;i++){dp[0][i] = value[0];}for(int i = 1; i < n;i++){for(int j = 1 ; j <= bagweight;j++){if(weight[i] > j){dp[i][j] = dp[i-1][j]; // 超重了就继承上方continue;}// 不选择idp[i][j] = max(dp[i][j],dp[i-1][j]); // 来自上方//选择idp[i][j] = max(dp[i][j],dp[i-1][j - weight[i]] + value[i]);}}// for(auto &i:dp){// for(auto &j:i){// cout << j << " ";// }// cout << endl;// }cout << dp[n - 1][bagweight];
}int main() {while(cin >> n >> bagweight) {solve();}return 0;
}
先看了视频再做的,思路相对清楚了很多,我感觉这个题目递归的过程不是很复杂,反而不好理解的是这个状态的定义,还有就是写的过程中,这个索引用着的感觉也有点奇怪,但是我说不清楚,还是写一个案例自己分析一下比较好,然后就是注意一下,本身在递推的过程中,我忽略的一个情况,就是当前的物品重量肯定放不进的情况,还有就是dp[i-1][j-weight],这个地方的j,我写成的bagWeight,这样就没有递推的过程了。
然后是滚动数组的写法,这样确实和二维数组有很多不一样的地方:
// 滚动数组
void solve_with_scrolling_array(){// 这里 dp 数组的定义就改变了,这里的dp[i]代表的是背包容量为i的时候,用所有的资源能装下的最大的价值vector<int> dp(bagweight+1,0), weight(n,0), value(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 = weight[0];i<bagweight;i++){// dp[i] = value[0];// }for(int i = 0 ; i < n;i++){ // 这里的循环代表的是选择的种类索引for(int j = bagweight; j >= weight[i];j--){// if(weight[i] > j) continue;dp[j] = max(dp[j],dp[j-weight[i]] + value[i]); //dp[j]其实就表示的是这个值不发生变化,也就是不选择}}cout << dp[bagweight];
}
首先是这个不能用第一个物品进行初始化,因为这样就是默认第一个物品加进去了,这样用后面倒序的方法的时候,会计算重复,之所以要用倒序,是因为一维数组无法存储左上和上的数据,这样使用当前层,就会导致当前的物品被计算了多次,所以要从后向前进行计算。特别的是这个终止的条件,其实就是之前二维数组 if 中需要继承上一个数值的一个处理。
1.2 分割等和子集
题目链接:. - 力扣(LeetCode)
class Solution {
public:bool canPartition(vector<int>& nums) {int sum = 0;for(auto& it: nums){sum += it;}if(sum % 2 != 0) return false; // 这种不可能分割成int n = nums.size(), bagweight = sum/2;vector<int> dp(bagweight + 1,0);for(int i = 0; i < n;i++){ // 相当于遍历每个物品for(int j = bagweight; j >= nums[i];j--){dp[j] = max(dp[j],dp[j - nums[i]] + nums[i]);}}if(dp[bagweight] == sum/2) return true;return false;// sort(nums.begin(),nums.end());// int tmp = 0;// int i = 0;// for(; i < nums.size();i++){// tmp += nums[i];// if(tmp == sum/2) break;// }// ++i;// int tmp1 = 0;// for(;i<nums.size();i++){// tmp1 += nums[i];// }// return tmp1 == tmp;}
};
做的磕磕绊绊的,主要是这个题的价值和重量是同一个东西,让我一时没反映过来。