算法设计与分析复习--分支界限法

文章目录

  • 上一篇
  • 分支界限法性质
  • 装载问题
  • 0-1背包问题
  • 单源最短路问题
  • 最大团问题
  • 下一篇

上一篇

算法设计与分析复习–回溯法(二)

分支界限法性质

分支界限法是按广度优先策略或最小耗费优先遍历问题的解空间树。

搜索解空间:

  1. 子集树
  2. 排列树

搜索方式:广度优先遍历(队列)或最小耗费优先(堆)

方法:确定解空间,设计合适的限界函数(在拓展时删除不必要的孩子结点),组织活结点表

但是由于每一层对应的cw, rw是不同的,所以需要用一个node的数据结构存储每一个节点的

装载问题

问题描述:n个集装箱要装到2艘重量分别 c 1 c_1 c1, c 2 c_2 c2的货轮,其中集装箱 i i i的重量为 w i w_i wi器满足集装箱重量之和小于两轮船载重。

最优装载方案:将第一艘船尽可能装满,将剩余的货箱装到第二搜轮船上。

约束函数:所装货物重量小于第一艘船载重
上界函数是:已装重量+剩余重量上界

使用队列的方式

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>using namespace std;const int N = 110;int a[N], n, c1, sum = 0, bw = 0;struct node
{int idx; // 层数int cw;  // 当前层的重量int rw;  // 剩余的重量
};void bfs()
{queue<node> q;q.push({0, 0, sum});while (q.size()){auto t = q.front();q.pop();bw = max(bw, t.cw); // 更新最大重量// 左扩展if (t.idx < n && t.cw + a[t.idx] <= c1){q.push({t.idx + 1, t.cw + a[t.idx], t.rw - a[t.idx]});}// 右扩展if (t.idx < n && t.cw + t.rw > bw){q.push({t.idx + 1, t.cw, t.rw - a[t.idx]});}}
}int main()
{scanf("%d%d", &n, &c1);for (int i = 0; i < n; i++){scanf("%d", &a[i]);sum += a[i];}bfs();printf("%d\n", bw);return 0;
}

在这里插入图片描述

利用优先级进行查找时
我们将利用当前结点的价值上界
c w + r w cw + rw cw+rw
进行堆的构造
重构堆需要

priority_queue<node, vector<node>, cmp> heap;
cmp为比较函数,不过要比较符相反

在这里插入图片描述
例如greater是返回更大的
而构造小根堆就用greater

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>using namespace std;const int N = 110;int a[N], n, c1, sum = 0, bw = 0;struct node
{int idx; // 层数int cw;  // 当前层的重量int rw;  // 剩余的重量
};struct cmp
{bool operator ()(const node &x, const node &y) const{return (x.cw + x.cw) < (y.cw + y.rw); // 优先队列的优先级按当前上界要用更大排,这里就要是小于}
};void bfs()
{priority_queue<node, vector<node>, cmp > heap;heap.push({0, 0, sum});while (!heap.empty()){auto t = heap.top();heap.pop();bw = max(bw, t.cw); // 更新最大重量// 左扩展if (t.idx < n && t.cw + a[t.idx] <= c1){heap.push({t.idx + 1, t.cw + a[t.idx], t.rw - a[t.idx]});}// 右扩展if (t.idx < n && t.cw + t.rw > bw){heap.push({t.idx + 1, t.cw, t.rw - a[t.idx]});}}
}int main()
{scanf("%d%d", &n, &c1);for (int i = 0; i < n; i++){scanf("%d", &a[i]);sum += a[i];}bfs();printf("%d\n", bw);return 0;
}

在这里插入图片描述


由于优先队列的方式更难一些所以后面实现都是优先队列的方式

0-1背包问题

求法与装载问题一样,不如说装载问题特化成了0-1背包问题

但是在右剪枝的求法上和回溯法一样
但是bound函数用法不同了,bound就是求上界的函数,并且求得是当前结点的上界

左剪枝:不超过背包容量
右剪枝:cv + rv >= bv
rv是利用贪心背包的方式求得的

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>using namespace std;
typedef pair<double, double> PDD;const int N = 110;int n, c;
vector<PDD> ob;
double bv = 0, sv = 0; // 将bv, sv初始化为0struct node
{int idx;double cw;double cv;double ub;bool operator< (const node &x) const{return ub < x.ub;//利用ub堆排序}
};bool cmp(PDD x, PDD y)
{return (x.second / x.first) > (y.second / y.first);//贪心排序
}double bound(node x)
{double rcv = x.cv, rw = c - x.cw;int i = x.idx;//不同于回溯法,在输入时改变i的值,因为要计算当前结点的上界while (i < n && ob[i].first <= rw){rw -= ob[i].first;rcv += ob[i].second;i++;}if (i < n)rcv += rw * (ob[i].second / ob[i].first);return rcv;
}void bfs()
{priority_queue<node> heap;heap.push({0, 0, 0, bound({0, 0, 0, 0})}); // 初始节点的上界需要计算while (heap.size()){auto t = heap.top();heap.pop();printf("{%d, %d, %.1lf}\n", (int)t.cw, (int)t.cv, t.ub);//搜索顺序可视化if (t.idx == n)//到达叶子结点{if (t.cv > bv){bv = t.cv;}continue; }if (t.cw + ob[t.idx].first <= c) // 向左走heap.push({t.idx + 1, t.cw + ob[t.idx].first, t.cv + ob[t.idx].second, t.ub}); node tmp = {t.idx + 1, t.cw, t.cv, bound({t.idx + 1, t.cw, t.cv, 0})};//需要填两次,定义临时变量if (bound(tmp) > bv)heap.push(tmp); // 向右走}
}int main()
{scanf("%d%d", &n, &c);for (int i = 0; i < n; i++){double w, v;scanf("%lf%lf", &w, &v);sv += v;ob.push_back({w, v});}sort(ob.begin(), ob.end(), cmp);bfs();printf("%d\n", (int)bv);return 0;
}

在这里插入图片描述
在这里插入图片描述

单源最短路问题

问题描述:给定一个带权有向图G = (V, E), 每条边的权值是一个正整数, 给定V中的一个顶点S,称作源点。要求:计算从源点到其他所有顶点的最短路径长度。

AcWing 850. Dijkstra求最短路 II

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>using namespace std;typedef pair<int, int> PII;const int N = 1e6 + 10;int h[N], e[N], w[N], ne[N], idx = 0;
int dist[N], pre[N];
vector<int> ans;
bool st[N];
int n, m;void add (int a, int b, int c)
{e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
}void traceback(int k)
{if (k == 0) return;ans.push_back(k);traceback(pre[k]);
}int dijkstra()
{memset(dist, 0x3f, sizeof dist);dist[1] = 0;priority_queue<PII, vector<PII>, greater<PII>> heap;heap.push({0, 1});// first表示距离, second表示节点编号,这是因为在优先队列中是优先按元祖第一个元素进行排序while (heap.size()){auto t = heap.top();heap.pop();int ver = t.second, distance = t.first;// ver表示节点编号if (st[ver])continue;st[ver] = true;for (int i = h[ver]; ~i; i = ne[i]){int j = e[i];if (dist[j] > distance + w[i])// 因为要遍历Ver相连的所有边i所以提前将源点到ver的最短距离记作distance, 而w[i]记录的是第i个节点到j的距离(权重)i是与ver相连的边 // 将与ver相连的边更新为最短路径值,j是i的下一条边是一个指针关系{dist[j] = distance + w[i];pre[j] = ver;heap.push({dist[j], j});}}}if (dist[n] == 0x3f3f3f3f) return -1;else {traceback(n);reverse(ans.begin(), ans.end());puts("最短路径为:");for (auto i : ans)printf("%d ", i);puts("");return dist[n];}
}int main ()
{cin >> n >> m;memset(h, -1, sizeof h);for (int i = 0; i < m; i ++){int a, b, c;scanf("%d%d%d", &a, &b, &c);add (a, b, c);}printf("路径长度为:%d", dijkstra());return 0;
}

在这里插入图片描述

最大团问题

问题描述:给定无向图G = (V, E)。如果 U ⊆ V U\subseteq V UV, 求对任意 u , v ∈ U u, v \in U u,vU ( u , v ) ∈ E (u, v) \in E (u,v)E, 则称U是G的完全子图。
最大团就是一个图含顶点数最大的完全图,且要是这个图的子集。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>using namespace std;const int N = 110;int g[N][N], n, m, bn;
vector<int> ans;struct node
{int idx;int cn;vector<int> x;int un;bool operator< (const node &p) const{return un < p.un;}
};bool constrain(node c)
{for (int i = 0; i < c.idx - 1; i ++)//这里i不能到c.idx不然就会有它自身到自身为0会返回false,{if (c.x[i] == 1 && g[c.idx][i + 1] == 0)//x的下标是从0开始,而g[i][j]的下标是从1开始,所以要进行调整return false;}return true;
}void bfs()
{priority_queue<node> heap;heap.push({0, 0, {}, n});while (heap.size()){auto t = heap.top();heap.pop();if (t.idx == n){if (t.cn > bn){ans = t.x;bn = t.cn;}continue;}node tmp = {t.idx + 1, t.cn + 1, t.x, t.un};tmp.x.push_back(1);//要提前加入,否则判断是少条件if (constrain(tmp))heap.push(tmp);tmp = {t.idx + 1, t.cn, t.x, t.un - 1};tmp.x.push_back(0);if (tmp.un >= bn)heap.push(tmp);}
}int main()
{scanf("%d%d", &n, &m);for (int i = 0; i < m; i ++){int a, b;scanf("%d%d", &a, &b);g[a][b] = g[b][a] = 1;}bfs();printf("%d\n", bn);for (auto val : ans) {printf("%d ", val);}return 0;
}

在这里插入图片描述
在这里插入图片描述

下一篇

未完待续

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/159852.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

APP自动化之Poco框架

今天给大家介绍一款自动化测试框架Poco&#xff0c;其脚本写法非常简洁、高效&#xff0c;其元素定位器效率更快&#xff0c;其本质基于python的第三方库&#xff0c;调试起来也会非常方便&#xff0c;能够很好的提升自动化测试效率&#xff0c;节省时间。 (一&#xff09;背景…

如何实现数据通过表格批量导入数据库

文章目录 1. 准备工作2. 创建数据库表3. 编写导入脚本4. 优化和拓展4.1 批量插入的优势4.2 错误处理4.3 数据验证4.4 数据转换 5. 总结 &#x1f389;如何实现数据通过表格批量导入数据库 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a;IT陈寒的博客&…

初学者必读书籍——两个月速成Python

想学Python的你是不是一直被它生涩难懂的劝退&#xff1f;作为一个自学入门的程序员&#xff0c;依靠这样几本书&#xff0c;两个月就学会了python。不卖关子&#xff0c;我学的就是”python编程三剑客“系列。那么接下来就让我给你介绍介绍吧。 1.《Python编程&#xff1a;从入…

OSG文字-osgText3D(5)

osgText3D 三维立体文字比二维平面文字显示效果更好&#xff0c;相对二维平面文字&#xff0c;它有非常好的立体显示效果。 在实际虚拟现实项目中&#xff0c;过多使用三维立体文字会降低染效率&#xff0c;加重渲染负担&#xff0c;相对平面二维文字&#xff0c;它占用的内存是…

掌握Katalon Studio 导入 swagger 接口文档,接口测试效率提升100%

katalon studio大家都已经不陌生了&#xff0c;是一款现在非常主流的自动化测试工具&#xff0c;包括了web、api、APP&#xff0c;甚至PC应用程序都可以使用它来完成自动化测试。 swagger是一款RESTFUL接口的文档在线自动生成软件&#xff0c;swagger是一个规范和完整的框架&a…

Python通过selenium调用IE11浏览器报错解决方法

前提 正常安装Python 工具&#xff0c;selenium 包可以正常导入。IE浏览器驱动 IEDriverServer.exe 已经正确放置到已经添加path目录的文件下。 报错现象&#xff1a; 解决方法 打开浏览器进入 internet 选项 切换到安全页签 &#xff0c;去除“应用保护模式” 再次调用验证…

C语言——I /深入理解指针(一)

一、内存和地址 1byte&#xff08;字节&#xff09; 8bit&#xff08;比特位&#xff09; 1KB 1024byte 1MB 1024KB 1GB 1024MB 1TB 1024GB 1PB 1024TB一个比特位可以存放二进制的0/1的一位 ⽣活中我们把⻔牌号也叫地址&#xff0c;在计算机中我们把内存单元的编号也称为…

真菌基因组研究高分策略(一):比较基因组揭示真菌菌丝和多细胞的起源

真菌是陆地和水生生态系统的重要组分&#xff0c;在有机质循环和跨营养级养分流通等过程中发挥着重要作用。随着测序技术的发展&#xff0c;高通量测序揭示了真菌群落巨大的系统发育和功能多样性&#xff0c;高质量真菌基因组的组装已经成为研究菌丝和潜在基因的进化起源的有力…

【c++】——类和对象(下) 万字解答疑惑

作者:chlorine 专栏:c专栏 目录 &#x1f6a9;再谈构造函数 &#x1f393;构造函数体赋值 &#x1f393;初始化列表 &#x1f6a9;explicit关键字 &#x1f6a9;static成员 &#x1f393;概念 面试题&#xff1a;计算创建多少个类对象 &#x1f393;特性 【问题】(非)…

智能合约安全漏洞与解决方案

// SPDX-License-Identifier: MIT pragma solidity ^0.7.0;import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.3/contracts/math/SafeMath.sol";/*智能合约安全在智能合约中安全问题是一个头等大事&#xff0c;因为智能合约不像其他语…

RH850 G3KH异常处理简述

目录 1.概述 2.异常处理后现场恢复 3.异常处理地址识别 4.小结 1.概述 我们首先来看&#xff0c;G3KH的关键寄存器&#xff0c;PSW PSW--Program status word PSW寄存器里有表征程序状态的flag&#xff0c;CPU操作状态的flag。如下 UM---是否是user mode&#xff1b;0--…

【JavaEE】Spring更简单的存储和获取对象(类注解、方法注解、属性注入、Setter注入、构造方法注入)

一、存储Bean对象 在这篇文章中我介绍了Spring最简单的创建和使用&#xff1a;Spring的创建和使用 其中存储Bean对象是这样的&#xff1a; 1.1 配置扫描路径 想要成功把对象存到Spring中&#xff0c;我们需要配置对象的扫描包路径 这样的话&#xff0c;就只有被配置了的包…

DDD神药:去哪儿结合DDD,实现架构大调优

尼恩说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格&#xff0c;遇到很多很重要的面试题&#xff1a; 谈谈你的DDD落地经验&#xff1f; 谈谈你对DDD的理解&#x…

那仰望的人

心底的孤独和叹息

LangChain库简介

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

维护工程师面经

文章目录 前言技能要求数据结构定义分类常用的数据结构 数据库原理数据的三级模式结构事务查询方式视图数据库范式 Java相关知识点总结 前言 本博客仅做学习笔记&#xff0c;如有侵权&#xff0c;联系后即刻更改 科普&#xff1a; 参考网址 技能要求 数据结构 参考网址 定…

毕业设计2349基于jsp的网上订餐系统【程序源码+文档+调试运行】

摘要 本文介绍了一个网上订餐系统的设计与实现。该系统分为前台用户模块和后台管理员模块&#xff0c;具有用户注册/登录、网站公告、菜品中心、购物车、用户后台、留言板等功能。管理员可以对用户信息、网站公告、菜品类别、菜品信息、订单信息、菜品评价信息、留言板信息和支…

Mac | Vmware Fusion | 分辨率自动还原问题解决

1. 问题 Mac的Vmware Fusion在使用Windows10虚拟机时&#xff0c;默认显示器配置如下&#xff1a; 开机进入系统并变更默认分辨率后&#xff0c;只要被 ⌘Tab 切换分辨率就会还原到默认&#xff0c;非常影响体验。 2. 解决方式 调整 设置 -> 显示器 -> 虚拟机分辨率…

Centos7安装Cesi(Supervisor集中管理工具)

Background CeSi 是 Supervisor 官方推荐的集中化管理 Supervisor 实例的 Web UI&#xff0c;该工具是用 Python 编写&#xff0c;基于 Flask Web 框架 。Superviosr 自带的 Web UI 不支持跨机器管理Supervisor 进程&#xff0c;功能比较简单&#xff0c;通过 CeSi 可以集中管理…

STM32F103C8T6第5天:独立看门狗、窗口看门狗、dma实验

1. 独立看门狗IWDG介绍&#xff08;341.45&#xff09; 什么是看门狗&#xff1f; 在由单片机构成的微型计算机系统中&#xff0c;由于单片机的工作常常会受到来自外界电磁场的干扰&#xff0c;造成程序的跑飞&#xff0c;而陷入死循环&#xff0c;程序的正常运行被打断&#…