当前位置: 首页 > wzjs >正文

网站地图生成器哪个好视频直播软件有哪些

网站地图生成器哪个好,视频直播软件有哪些,惠州seo网站推广,龙岩天宫山缆车门票多少钱动态规划之背包问题详解 背包问题是动态规划领域的核心内容,也是算法竞赛和面试中的常考题型。本文系统性地介绍各类背包问题的解题思路、状态转移方程和优化技巧,帮助读者全面掌握这一重要算法范式。 一、01背包问题 问题描述 有 N 件物品和一个容量…

动态规划之背包问题详解

背包问题是动态规划领域的核心内容,也是算法竞赛和面试中的常考题型。本文系统性地介绍各类背包问题的解题思路、状态转移方程和优化技巧,帮助读者全面掌握这一重要算法范式。

一、01背包问题

问题描述

有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。第 i 件物品的体积是 vi,价值是 wi。求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。

核心思想

01背包的核心在于每件物品只有选与不选两种状态,状态转移方程为:

f[i][j] = max(f[i-1][j], f[i-1][j-v[i]] + w[i])

代码实现

二维解法(基础)
#include <iostream>
#include <algorithm>
using namespace std;const int MAXN = 1005;
int f[MAXN][MAXN];  // f[i][j]表示前i件物品放入容量为j的背包的最大价值
int v[MAXN], w[MAXN]; // 体积和价值int main() {int n, m;cin >> n >> m;for (int i = 1; i <= n; i++) cin >> v[i] >> w[i];for (int i = 1; i <= n; i++) {for (int j = 0; j <= m; j++) {f[i][j] = f[i-1][j]; // 不选第i件物品if (j >= v[i]) // 能选第i件物品f[i][j] = max(f[i][j], f[i-1][j-v[i]] + w[i]);}}cout << f[n][m];return 0;
}
一维优化(空间优化)
#include <iostream>
#include <algorithm>
using namespace std;const int MAXN = 1005;
int f[MAXN]; // 优化为一维数组
int v[MAXN], w[MAXN];int main() {int n, m;cin >> n >> m;for (int i = 1; i <= n; i++) cin >> v[i] >> w[i];for (int i = 1; i <= n; i++)for (int j = m; j >= v[i]; j--) // 逆序遍历避免覆盖f[j] = max(f[j], f[j-v[i]] + w[i]);cout << f[m];return 0;
}

关键点

  1. 逆序遍历保证每个物品只被选取一次

  2. 状态转移基于前一个状态的值

  3. 时间复杂度O(NV),空间复杂度O(V)

二、完全背包问题

问题描述

有 N 种物品和一个容量是 V 的背包,每种物品都有无限件可用。求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。

核心思想

与01背包的区别在于物品可以无限次选取,状态转移方程为:

f[i][j] = max(f[i-1][j], f[i][j-v[i]] + w[i])

代码实现

二维解法
#include <iostream>
#include <algorithm>
using namespace std;const int MAXN = 1005;
int f[MAXN][MAXN];
int v[MAXN], w[MAXN];int main() {int n, m;cin >> n >> m;for (int i = 1; i <= n; i++) cin >> v[i] >> w[i];for (int i = 1; i <= n; i++) {for (int j = 0; j <= m; j++) {f[i][j] = f[i-1][j];if (j >= v[i])f[i][j] = max(f[i][j], f[i][j-v[i]] + w[i]);}}cout << f[n][m];return 0;
}
一维优化
#include <iostream>
#include <algorithm>
using namespace std;const int MAXN = 1005;
int f[MAXN];
int v[MAXN], w[MAXN];int main() {int n, m;cin >> n >> m;for (int i = 1; i <= n; i++) cin >> v[i] >> w[i];for (int i = 1; i <= n; i++)for (int j = v[i]; j <= m; j++) // 正序遍历允许重复选取f[j] = max(f[j], f[j-v[i]] + w[i]);cout << f[m];return 0;
}

与01背包的区别

  1. 正序遍历允许物品多次选取

  2. 状态转移基于当前行而不是上一行

  3. 时间复杂度仍为O(NV),但状态转移逻辑不同

三、多重背包问题

问题描述

有 N 种物品和一个容量是 V 的背包。第 i 种物品最多有 si 件,每件体积是 vi,价值是 wi。求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。

二进制优化

当物品数量较大时,使用二进制优化将多重背包转化为01背包:

#include <iostream>
#include <algorithm>
using namespace std;const int MAXN = 25000; // 1000*log2000 ≈ 22000
int f[MAXN], v[MAXN], w[MAXN];int main() {int n, m, cnt = 0;cin >> n >> m;// 二进制拆分for (int i = 1; i <= n; i++) {int a, b, s;cin >> a >> b >> s;int k = 1;while (k <= s) {cnt++;v[cnt] = a * k;w[cnt] = b * k;s -= k;k *= 2;}if (s > 0) {cnt++;v[cnt] = a * s;w[cnt] = b * s;}}// 01背包求解for (int i = 1; i <= cnt; i++)for (int j = m; j >= v[i]; j--)f[j] = max(f[j], f[j-v[i]] + w[i]);cout << f[m];return 0;
}

优化原理

  1. 将数量s拆分为2的幂次之和(1,2,4,...,2^k,s-2^k)

  2. 每个拆分后的物品视为独立的01背包物品

  3. 优化时间复杂度从O(NVS)降为O(NVlogS)

四、分组背包问题

问题描述

给定N组物品和一个容量为V的背包。每组物品有若干个,但在同一组内,最多只能选择一件物品。每件物品有其对应的体积和价值。目标是选择物品放入背包,使得总体积不超过背包容量,且总价值最大。

状态转移

f[i][j] = max(f[i-1][j], max_{1≤k≤s_i}(f[i-1][j-v_{ik}] + w_{ik}))

代码实现

#include <iostream>
#include <algorithm>
using namespace std;const int MAXN = 105;
int f[MAXN][MAXN], v[MAXN][MAXN], w[MAXN][MAXN], s[MAXN];int main() {int n, m;cin >> n >> m;for (int i = 1; i <= n; i++) {cin >> s[i];for (int j = 1; j <= s[i]; j++)cin >> v[i][j] >> w[i][j];}for (int i = 1; i <= n; i++) {for (int j = 0; j <= m; j++) {f[i][j] = f[i-1][j]; // 不选该组任何物品for (int k = 1; k <= s[i]; k++) {if (j >= v[i][k])f[i][j] = max(f[i][j], f[i-1][j-v[i][k]] + w[i][k]);}}}cout << f[n][m];return 0;
}

优化技巧

  1. 使用一维数组优化空间

  2. 每组内部循环放在最内层

  3. 逆序遍历背包容量

五、二维费用背包问题

问题特点

背包限制条件从单一容量变为两个维度(如重量和体积、金钱和时间等)

潜水员问题

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;const int MAXM = 85, MAXN = 25;
int f[MAXM][MAXN]; // f[j][k]: 氧气至少j,氮气至少k的最小重量
int O2[MAXN], N2[MAXN], W[MAXN];int main() {int m, n, k;cin >> m >> n >> k;memset(f, 0x3f, sizeof f);f[0][0] = 0;for (int i = 1; i <= k; i++)cin >> O2[i] >> N2[i] >> W[i];for (int i = 1; i <= k; i++) {for (int j = m; j >= 0; j--) {for (int k = n; k >= 0; k--) {int nj = max(0, j - O2[i]);int nk = max(0, k - N2[i]);f[j][k] = min(f[j][k], f[nj][nk] + W[i]);}}}cout << f[m][n];return 0;
}

宠物小精灵收服

#include <iostream>
#include <algorithm>
using namespace std;const int MAXM = 505, MAXN = 1005;
int f[MAXN][MAXM]; // f[j][k]: 使用j个球,消耗k体力的最大收服数
int balls[MAXN], damage[MAXM];int main() {int n, m, k;cin >> n >> m >> k;m--; // 保留1点体力for (int i = 1; i <= k; i++)cin >> balls[i] >> damage[i];for (int i = 1; i <= k; i++) {for (int j = n; j >= balls[i]; j--) {for (int k = m; k >= damage[i]; k--) {f[j][k] = max(f[j][k], f[j-balls[i]][k-damage[i]] + 1);}}}int max_catch = f[n][m], min_damage = 0;for (int k = 0; k <= m; k++) {if (f[n][k] == max_catch) {min_damage = k;break;}}cout << max_catch << " " << m + 1 - min_damage;return 0;
}

六、混合背包问题

问题描述

混合背包结合了01背包、完全背包和多重背包,需要根据物品类型选择不同的处理策略。

通用解法

#include <iostream>
#include <algorithm>
using namespace std;const int MAXM = 205;
int dp[MAXM];// 01背包处理
void zeroOnePack(int weight, int value, int capacity) {for (int j = capacity; j >= weight; j--)dp[j] = max(dp[j], dp[j-weight] + value);
}// 完全背包处理
void completePack(int weight, int value, int capacity) {for (int j = weight; j <= capacity; j++)dp[j] = max(dp[j], dp[j-weight] + value);
}// 多重背包处理(二进制优化)
void multiplePack(int weight, int value, int count, int capacity) {if (weight * count >= capacity) {completePack(weight, value, capacity);return;}int k = 1;while (k < count) {zeroOnePack(k*weight, k*value, capacity);count -= k;k *= 2;}zeroOnePack(count*weight, count*value, capacity);
}int main() {int m, n;cin >> m >> n;for (int i = 0; i < n; i++) {int w, v, s;cin >> w >> v >> s;if (s == 0) completePack(w, v, m);else if (s == 1) zeroOnePack(w, v, m);else multiplePack(w, v, s, m);}cout << dp[m];return 0;
}

七、有依赖的背包问题

金明的预算方案

#include <iostream>
#include <algorithm>
using namespace std;const int MAXN = 32005;
int main_w[65], main_v[65];
int annex_w[65][3], annex_v[65][3];
int f[MAXN];int main() {int n, m;cin >> n >> m;for (int i = 1; i <= m; i++) {int v, p, q;cin >> v >> p >> q;if (!q) {main_w[i] = v;main_v[i] = v * p;} else {annex_w[q][0]++;annex_w[q][annex_w[q][0]] = v;annex_v[q][annex_w[q][0]] = v * p;}}for (int i = 1; i <= m; i++) {if (!main_w[i]) continue;for (int j = n; j >= main_w[i]; j--) {// 只选主件f[j] = max(f[j], f[j-main_w[i]] + main_v[i]);// 主件+附件1if (j >= main_w[i] + annex_w[i][1])f[j] = max(f[j], f[j-main_w[i]-annex_w[i][1]] + main_v[i] + annex_v[i][1]);// 主件+附件2if (j >= main_w[i] + annex_w[i][2])f[j] = max(f[j], f[j-main_w[i]-annex_w[i][2]] + main_v[i] + annex_v[i][2]);// 主件+附件1+附件2if (j >= main_w[i] + annex_w[i][1] + annex_w[i][2])f[j] = max(f[j], f[j-main_w[i]-annex_w[i][1]-annex_w[i][2]] + main_v[i] + annex_v[i][1] + annex_v[i][2]);}}cout << f[n];return 0;
}

八、总结与拓展

1.背包问题通用解法框架

  1. 定义状态:明确dp数组的含义

  2. 初始化状态:处理边界条件

  3. 状态转移:根据问题类型选择合适的转移方程

  4. 确定结果:找到最终状态对应的解

2.优化技巧对比

问题类型空间优化时间优化特殊技巧
01背包逆序一维
完全背包正序一维
多重背包一维二进制拆分单调队列优化
分组背包一维组内循环
二维费用二维两个限制条件
混合背包一维分类处理
依赖背包一维主附件组合

3.实际应用场景

  1. 资源分配问题

  2. 投资组合优化

  3. 生产计划制定

  4. 货物装载优化

  5. 时间管理调度

http://www.dtcms.com/wzjs/547931.html

相关文章:

  • 珠海在线网站制作公司有几个网站打不开
  • 在线制作论坛网站一个网站怎么做软件好用吗
  • 监控性能网站模板国家企业信用网(江苏)
  • 郑州春蕾网站建设网站模板好
  • 文章管理系统网站模板武器系统软件开发文档
  • 怎么套用网站模板做二维码签到的网站
  • 域名备案网站购买用ps做网站的临摹
  • 潍坊市坊子区建设局网站青海论坛网站建设
  • paypal客户端网站建设评价wordpress qq悬浮窗
  • 宁波网站关键词排名推广高德是外国公司吗?
  • 焦作电子商务网站建设实例seo外链推广员
  • 做淘宝需要知道什么网站深圳宝安区医院
  • 螺旋钢管网站建设网站制作类软件推荐
  • 建网站用html电子商务网站的建设与规划书
  • 哪个网站做螺丝生意好企业网页制作公司
  • 前端ui设计是什么广州seo外包
  • 做企业网站宁波企业建站程序
  • 淘宝上做网站可信吗北京网站设计公司排行榜
  • 建立手机也可浏览的网站教程网站自助建站系统
  • Wordpress 报表的插件全能优化大师
  • html网站列表怎么做德州建设公司网站
  • 网站建设责任分解现在什么语言做网站最好
  • 海报设计网站免费微信网站开发怎么做
  • 申请域名之后如何做网站石家庄网站建设咨询薇
  • 重庆市建筑工程信息官方网站网站建设代理成本
  • 网站pc和手机端怎么验证网站
  • 如何用织梦做网站详细教程微网站 获取手机号
  • 大型网站维护费一年多少单一产品网站如何做seo
  • 西部数码 网站管理手机端官网设计
  • 专业建站模板做网站样式模板