【算法训练记录——Day41】

发布于:2024-07-05 ⋅ 阅读:(22) ⋅ 点赞:(0)


背包!!

1.理论基础——代码随想录

在这里插入图片描述
主要掌握01背包和完全背包
物品数量: 只有一个 —— 01背包;
无数个 —— 完全背包;
不同物品数量不同 —— 多重背包;
按组打包,每组最多选一个 —— 分组背包;

2.纯01背包_kamacoder46

题目描述:有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。
          每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大

思路:

  1. 暴力方法:所有物品只有两种状态,装或者不装,因此可以用回溯法搜索所有情况,然后选择
  2. 二维数组dp01背包:
    1. dp[i][j]表示容量为 j 的背包从前i件(0=<x<i)物品里随便装所取得的物品最大价值
    2. 当物品价值最大时,第i件物品如果不在背包里,那么dp[i][j] = dp[i-1][j];
      如果在背包里,dp[i][j] = dp[i-1][j-w[i]] + v[i];
      dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i]);
    3. 初始化: 背包容量为0,价值为0;dp[i][0] = 0;
      从定义可知,i 从 1开始有意义, i > 0;
      补充:当 i= 0 时,因为i>0时,dp[i][j]都与dp[i-1][j]相关,因此需要初始化i= 0;如果 j < w[0],那么不用管,本来就放不进去,但如果 j > w[0],此时的dp[0][j]就需要置为v[0]了,因为第一个能放入背包。
    4. 顺序:i从1 ~ n,j 从 w ~ 0;
      先遍历物品和先遍历物品,都差不多
    5. dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i]);
	#include <iostream>
	#include <vector>
	using namespace std;
	
	int main() {
	    int M, N;
	    cin >> M >> N;
	    vector<vector<int>> item(M, vector<int>(2, 0));
	    
	    for(int i = 0; i < M; i++) {
	        cin >> item[i][0];
	    }
	    for(int i = 0; i < M; i++) {
	        cin >> item[i][1];
	    }
	    
	    vector<vector<int>> dp(M, vector<int>(N + 1, 0));
	    
	    for (int j = item[0][0]; j <= N; j++) {
	        dp[0][j] = item[0][1];
	    }
	    
	    for(int i = 1; i < M; i++) {
	        for(int j = 0; j <= N; j++) {
	            if(item[i][0] > j) dp[i][j] = dp[i-1][j];
	            else dp[i][j] = max(dp[i-1][j], dp[i-1][j-item[i][0]] + item[i][1]);
	        }
	    }
	    
	    cout << dp[M-1][N];
	    
	    return 0;
	}

方法二:一维数组
dp[i][j] = max(dp[i-1][j], dp[i-1][j-item[i][0]] + item[i][1])
可以用dp[i][j]来保存dp[i-1][j],从而转换成一维数组
dp[j] = max(dp[j], dp[j-w[i]+item[i][1]);

	#include <iostream>
	#include <vector>
	using namespace std;
	
	int main() {
	    int M, N;
	    cin >> M >> N;
	    vector<vector<int>> item(M, vector<int>(2, 0));
	    
	    for(int i = 0; i < M; i++) {
	        cin >> item[i][0];
	    }
	    for(int i = 0; i < M; i++) {
	        cin >> item[i][1];
	    }
	    
	    vector<int> dp(N + 1, 0);
	
	    for(int i = 0; i < M; i++) {
	        for(int j = N; j >= item[i][0]; j--) {
	            dp[j] = max(dp[j], dp[j-item[i][0]] + item[i][1]);
	        }
	    }
	    
	    cout << dp[N];
	    
	    return 0;
	}

3.leetcode_416分割等和子集

在这里插入图片描述
思路:


网站公告

今日签到

点亮在社区的每一天
去签到