Knapsack Problem
创始人
2024-01-20 04:01:54
0

背包九讲


0-1 knapsack problem

01背包-牛客网

已知一个背包最多能容纳体积之和为V的物品,现有 n 个物品,第 i 个物品的体积为 vi , 重量为 wi,求当前背包最多能装多大重量的物品?

使用动态规划来解决01背包问题:

首先定义dp数组:dp[i][j] := 0-i号物品面对容量为j的背包所能获得的最大重量

状态转移方程:

dp[i][j]={dp[i−1][j],容量不足,不放入物品imax(dp[i−1][j],dp[i−1][j−v[i]]+w[i]),考虑拿这件物品能否获得更大重量dp[i][j]= \begin{cases} dp[i-1][j],\quad 容量不足,不放入物品i\\ max(dp[i - 1][j], dp[i - 1][ j - v[i]] + w[i]), \quad 考虑拿这件物品能否获得更大重量 \end{cases} dp[i][j]={dp[i−1][j],容量不足,不放入物品imax(dp[i−1][j],dp[i−1][j−v[i]]+w[i]),考虑拿这件物品能否获得更大重量​

class Solution {
public:int knapsack(int V, int n, vector >& vw) {vector> dp(n + 1, vector(V + 1, 0));for (int i = 1; i <= n; ++i) {for (int j = 1; j <= V; ++j) {if (j < vw[i - 1][0]) {dp[i][j] = dp[i - 1][j];} else {dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - vw[i - 1][0]] + vw[i - 1][1]);}}}return dp[n][V];}
};

由于dp问题具有无后效性,可以采用滚动数组的方式节省内存,此时状态转移方程化为:

if j >= v[i]:dp[j] = max(dp[j], dp[j - v[i]] + w[i]);

Charm Bracelet:定义一维的dp数组,每次从后向前刷新dp数组:

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

full knapsack problem

完全背包-牛客网

你有一个背包,最多能容纳的体积是V。现在有n种物品,每种物品有任意多个,第 i 种物品的体积为vi,价值为wi,求这个背包至多能装多大价值的物品?

完全背包的状态转移方程和01背包极其相似:

dp[i][j]={dp[i−1][j],容量不足,不放入物品imax(dp[i−1][j],dp[i][j−v[i]]+w[i]),考虑拿这件物品能否获得更大重量dp[i][j]= \begin{cases} dp[i-1][j],\quad 容量不足,不放入物品i\\ max(dp[i - 1][j], dp[i][ j - v[i]] + w[i]), \quad 考虑拿这件物品能否获得更大重量 \end{cases} dp[i][j]={dp[i−1][j],容量不足,不放入物品imax(dp[i−1][j],dp[i][j−v[i]]+w[i]),考虑拿这件物品能否获得更大重量​
而且,考虑使用滚动数组压缩空间,完全背包和01背包的状态转移方程是一样的。区别在于dp数组的遍历方式:完全背包问题必须顺序推导dp数组,而01背包采用逆序推导dp数组

if j >= v[i]:dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
class Solution {public:vector knapsack(int v, int n, vector >& nums) {// write code herevector res;vector dp(v + 1, 0);vector pack(v + 1, -255);pack[0] = 0;for (int i = 0; i < n; ++i) {for (int j = 0; j <= v; ++j) {if (j >= nums[i][0]){dp[j] = max(dp[j], dp[j - nums[i][0]] + nums[i][1]);pack[j] = max(pack[j], pack[j - nums[i][0]] + nums[i][1]);	//只考虑能从0一步步跳到v的w}}}res.push_back(dp[v]);if (pack[v] > 0) {res.push_back(pack[v]);} else {res.push_back(0);}return res;}
};

Piggy-Bank


fractional knapsack problem

与上面的两种背包问题不同,分数背包问题(物品可以被任意分割)比较简单,可以用贪心算法解决:每次都选择单位价值最大的物品装入背包,如果未满,则选择下一个价值次大的物品装入背包

圣诞老人的礼物-百练

#include 
#include 
#include 
using namespace std;#define MAXN (100+10)struct Box {int v;int w;double density;Box() {}Box(int vv, int ww) :v(vv), w(ww), density(double(v) / w) {}bool operator<(const Box& b) {return density < b.density;}
};int n, weigth;
double total_w = 0;
double total_v = 0;
Box boxes[MAXN];int main() {cin >> n >> weigth;int v, w;for (int i = 0; i < n; ++i) {cin >> v >> w;boxes[i] = Box(v, w);}sort(boxes, boxes + n);for (int i = n - 1; i >= 0; --i) {if (total_w + boxes[i].w < weigth) {total_w += boxes[i].w;total_v += boxes[i].v;}else {total_v += boxes[i].density * (weigth - total_w);total_w = weigth;}}printf("%.1f\n", total_v);return 0;
}

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AWR报告解读 WORKLOAD REPOSITORY PDB report (PDB snapshots) AW...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
群晖外网访问终极解决方法:IP... 写在前面的话 受够了群晖的quickconnet的小水管了,急需一个新的解决方法&#x...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
Azure构建流程(Power... 这可能是由于配置错误导致的问题。请检查构建流程任务中的“发布构建制品”步骤,确保正确配置了“Arti...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...