优先队列

AStar 启发函数设计(老物)

点点圈 提交于 2019-11-29 12:08:51
作为我出山的第一篇日志,怎么也得写篇对得起我身份和地位的文章吧? 先容我吐槽一下不小心发的贴图,那个只是我不小心收藏了隔壁兄弟班的课表就别大家这么热情的 BB 我感到很有压力,额,废话不多说,立刻进入正题吧。 简单说一下 AStar ( A* )算法,这是一种根据启发函数图遍历算法雏形。 举个栗子,如果你身处迷宫,但你知道出口的方向,那么你应该会尝试往出口方向前进,那么,第一种启发函数就被确定了,取出周围的点,根据一个欧拉距离运算来确定各个点距离出口还有多远,从而选择距离较近的点进行移动,这就是一种由启发函数进行导向的算法模型,假若还不了解什么是启发式搜索请自行移步到百度百科。 好滴,其实上面只是作为自己的一种理解让大家好明白我接下来要说明的内容是关于哪些方面的,如果不是计算机专业的同学看到这里,请自觉跳到最底通过看图例来感受一下启发式函数搜索的魅力吧(笑)。 通常的 A* 算法 通常的 A* 算法主要有两种估值函数,曼哈顿距离以及距离消耗步数进行结合,最终得到权值 F 可以做为下一步将要移动的位置,举个图例就是: 注:右图左上角为图形边界 30*30 ,右下角为搜索次数,起始点为(12,5),终止点为(12,24)。最终搜索到的点为 423*4 (最大值)。 根据上图我们可见,通常 A* 寻路可以获得最短路径,但我这里的想法是应用在游戏寻路中,为了达到这个目的我不得不做出一些牺牲

洗衣服和烘干衣服(优先队列+思维)

别来无恙 提交于 2019-11-29 04:58:43
题意: 给你n件衣服,w个洗衣机,m个烘干机。 烘干必须等洗完了才能烘干,多台机器可以同时工作。 思路: 两次优先队列:烘干衣服那边的优先队列有点难想到,而且倒过来遍历:最后一件衣服尽量用快的烘干机烘干也不容易想到。 代码中有注释。 1 #define IOS ios_base::sync_with_stdio(0); cin.tie(0); 2 #include <cstdio>//sprintf islower isupper 3 #include <cstdlib>//malloc exit strcat itoa system("cls") 4 #include <iostream>//pair 5 #include <fstream>//freopen("C:\\Users\\13606\\Desktop\\草稿.txt","r",stdin); 6 #include <bitset> 7 //#include <map> 8 //#include<unordered_map> 9 #include <vector> 10 #include <stack> 11 #include <set> 12 #include <string.h>//strstr substr 13 #include <string> 14 #include <time.h>//srand((

C++模板学习之优先队列实现

Deadly 提交于 2019-11-29 03:21:31
转载:https://www.cnblogs.com/muzicangcang/p/10579250.html 今天将继续将强C++模板类的学习,同时为了巩固已经学习过的数据结构中有关优先队列的知识,我将会使用模板类来实现自己的优先队列。在给出具体实现之前,我要先介绍一下什么是优先队列,聊以为复习吧。 在某些情况下,我们会收集一些元素,处理当前元素的最大值,然后再收集更多数据,再处理此时的最大值。这就要求我们设计的数据结构能够随时访问元素集合中的最大值和能够随时插入数据。优先队列即可以实现这种功能。 优先队列 优先队列的实现有两种思路,第一是在数据插入时保存数据元素的有序性,这意味着我们能够以O(1)的时间复杂度来访问元素中的最大值。但是我们在数据进行插入的时候,对寻找数据的合适位置的访问操作的最坏时间复杂度为O(N)。第二种思路是构建一个堆,他能够让我们以N(1)的时间复杂度来访问元素中的最大值,而以O(logN)的时间复杂度来调整堆,以便将元素插入到合适的位置。综上所述,在具体实现优先队列的时候需要根据待处理的元素量级来确定到底使用哪种思路。很明显,当数量级较小的时候,适合使用第一种思路;当数量级较大的时候,第二种思路将比较好。 首先简单介绍一下什么是堆。 1、堆是一种数据结构,他是一棵完全二叉树 2、在堆中,每个父节点都大于等于它的两个孩子结点,被称为堆有序 3

看完这篇你还不知道这些队列,我这些图白作了

*爱你&永不变心* 提交于 2019-11-29 00:47:42
队列(queue)是一种采用先进先出(FIFO)策略的抽象数据结构,即最先进队列的数据元素,同样要最先出队列。队列跟我们排队买票一样,先来排队的肯定先买票,后来排队的的后买到票。队列如下图所示: 队列有两个重要的概念,一个叫队头,一个叫队尾,队头指向的是第一个元素,而队尾指向的是最后一个元素。队列跟栈一样也是访问受限制的,所以队列也只有两个主要的操作: 入队(enqueue)操作 和 出队(dequeue)操作 。入队操作就是将一个元素添加到队尾,出队操作就是从队头取出一个元素。 队列的底层实现可以用数组和链表,基于数组实现的队列叫作 顺序队列 ,基于链表实现的队列叫作 链式队列 ,下面我们分别用数组和链表来简单的实现这两种队列。 基于数组的队列 不管使用那种方式来实现队列,都需要定义两个指针分别指向队头和队尾,本文中我们用 head 指向队头, tail 指向队尾,后面的示例中这将默认使用这个,有特殊的地方我会进行说明,先来看看顺序队列的入队、出队操作。 图中可以看出,入队时,队尾往后移动,队头保持不变,出队是队头往后移动,队尾保持不变。入队、出队操作的逻辑都比较简单,可能你有疑问的地方是: 出队时为什么队头要往后移动而不是一直指向数组下标为 0 的位置? 为什么呢?如果我们保持队头一直指向数组下标为 0 的位置,那每次出队操作后,后面的数据都需要往前挪一位

《面试》-- 简单使用Python解决图结构的最小路径 -- Dijkstra算法

不打扰是莪最后的温柔 提交于 2019-11-28 22:02:30
写在前面 在你观看这篇博客之前,我必须种草、安利一个讲DFS、BFS、Dijkstra的视频,非常建议想学习经典图算法的猴子去看看,时间不长但是很精辟别忘了点赞啊,链接: https://www.bilibili.com/video/av25829980?from=search&seid=12399862396157246554 回归正题 图如图所示,假设起点为A,找出起点到剩下各个点的最短路径。 思路:本人肤浅,只知道Dijkstra算法就是专门用来解决这个问题,直接用Dijkstra就可以了。 过程: 代码: import heapq Graph = { 'A': {'B': 5, 'C': 1}, 'B': {'A': 5, 'C': 2, 'D': 1}, 'C': {'A': 1, 'B': 2, 'D': 4, 'E': 8}, 'D': {'B': 1, 'C': 4, 'E': 3, 'F': 6}, 'E': {'C': 8, 'D': 3}, 'F': {'D': 6} } def Dijkstra(Graph, start): assert isinstance(Graph, dict) assert isinstance(start, str) assert start in Graph.keys() # 使用优先队列实现 pqueue = [] heapq

csp 201709-2 优先队列模拟

霸气de小男生 提交于 2019-11-28 20:18:21
数据规模:    用优先队列对各个事件的发生先后记录即可: #include<iostream> #include<queue> using namespace std; int key[1001]; struct node { int no; int begin; int end; int type;//表示借,1表示时在还 node(int no, int begin,int end, int type):no(no),begin(begin),end(end),type(type) { } friend bool operator <(node a, node b) { if(!a.type) { if(!b.type)//都是借 { return a.begin>b.begin; } else//借遇到还的 { return (a.begin>=(b.begin+b.end)); } } else { if (!b.type) { return (a.begin+a.end)>b.begin; } else { //都是还 if((a.begin+a.end)>(b.begin+b.end)) return true; else if((a.begin+a.end)==(b.begin+b.end)) return a.no > b.no; else return

单调队列优化多重背包问题 + 例题

元气小坏坏 提交于 2019-11-28 18:44:09
例题: https://www.acwing.com/problem/content/6/ 多重背包除了可以使用二进制加速,还可以使用单调队列加速,并且单调队列会更快 正常的多重背包的dp方程: 其中 k 为物品的多少, v[i]为物品的体积, w[i]为物品的价值 可以看到转移的时候,dp[i][j]只和dp[i][j-k*v[i]]有关,并且是取动态的固定区间大小的区间最值,可以考虑使用优先队列优化。 使用优先队列要求我们j由小到大遍历,因此此题不方便使用一维数组简化空间,但是可以使用滚动数组减少空间 (假如使用一维数组,那么之前计算过的数值就会无限叠加,如图j-3v会叠加到j 然后j再带着j-3v的值不断往前叠加) 使用滚动数组的时候,设 dp[2][i] i:表示此时背包体积多少 dp数组则表示当体积为i的时候可以获得的最优解 每次使用的时候dp[t][i] , 每次需要滚动的时候t^=1 即可 还有一个问题,就是优先队列如何维护数值。 假如直接维护dp[i][k] + (j-k)/v[i] * w[i] (也就是维护dp的值),那么i增加的时候,之前的dp对dp[i]的贡献全部会改变,比如: 当j+=v的时候 此时优先队列里维护的东西就变了。 所以需要维护一个不受距离影响的值,具体看代码: #include<bits/stdc++.h> using namespace

POJ-1511(Dijkstra+优先队列优化)

好久不见. 提交于 2019-11-28 10:00:21
Invitation Cards POJ-1511 从这道题我还是发现了很多的问题,首先就是快速输入输出,这里的ios::---这一行必须先放在main函数第一行,也就是输入最开始的前面,否则系统疯狂报WA。 其次就是,ios的位置没有错之后又疯狂地报TLE,就是超时了,这个问题要不就是算法的复杂度,还有就是输入输出还是不够快,所以首先排除输入输出的问题,所以我把ios改成了scanf所以这题就过了。 事实证明,ios的方法还是没有scanf快,所以以后还是使用scanf. 其次就是这个算法本身的问题,这个其实已经比n*n的算法快多了,由于本题的数据量太大,这个版本也是很险才过的。 关于本题的思路主要就是正着走一遍,然后倒着走一遍,最后累加起来就可以了。 推荐一个多方法的博客: https://blog.csdn.net/qq_39665840/article/details/81437812 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<queue> #include<algorithm> #include<vector> using namespace std; const int INF=0x3f3f3f3f; int p,q;//p-stops;q-lines

stl(优先队列操作)

谁都会走 提交于 2019-11-28 04:08:23
http://codeforces.com/gym/101911/problem/C Recently Monocarp has created his own mini-laboratory! The laboratory contains n bacteria. Monocarp knows that he can merge any two bacteria having equal sizes, and the resulting bacterium will have the size equal to the sum of sizes of merged bacteria. For example, if two bacteria having sizes equal to 7 merge, one bacterium with size 14 is the result. It becomes hard to watch for many bacteria, so Monocarp wants to merge all of them into one bacterium. It may not be possible to do this with the bacteria Monocarp has, so he can buy any number of

C++ STL:优先队列的使用详解

陌路散爱 提交于 2019-11-28 03:58:57
  堆是一个很重要的数据结构,那么我们如何更加简洁的去写大根/小根堆呢?   对于很多语言来说,只能一步一步手打,但是对于C++来说,写大根小根堆就简便得多,因为C++中有一个容器叫做priority_queue,这个容器和queue都包含在头文件<queue>中,priority_queue容器叫做可以模拟优先队列,这个容器可以将你输入的数据按顺序储存在容器里,插入元素和删除元素操作的时间复杂度都是log N,但是查询堆顶元素(最值)的时间复杂度是O(1),插入和删除用:a.push(x)和a.pop()来进行,返回堆顶元素的操作是a.top(),由于优先队列自身的特性,它本身只能写大根堆,但是如果我们将输入时的数据都变为它的相反数,输出时再变为相反数,这样就可以将优先队列变成小根堆,当然我们也可以重载‘<’来实现。   下面介绍一道相关的水题: 题目描述 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。 每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过 n-1 n − 1 次合并之后, 就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。 因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为 1 1