普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (graph theory)),且其所有边的权值之和亦为最小。该算法于1930年由捷克数学家沃伊捷赫·亚尔尼克(英语:Vojtěch Jarník)发现;并在1957年由美国计算机科学家罗伯特·普里姆(英语:Robert C. Prim)独立发现;1959年,艾兹格·迪科斯彻再次发现了该算法。因此,在某些场合,普里姆算法又被称为DJP算法、亚尔尼克算法或普里姆-亚尔尼克算法。

——来自百度百科

当我们将Prim算法用于迷宫生成时,情况有些不同,维基百科中给出了随机Prim迷宫生成算法的解释及实现过程:

Randomized Prim's algorithm

This algorithm is a randomized version of Prim's algorithm.

  1. Start with a grid full of walls.
  2. Pick a cell, mark it as part of the maze. Add the walls of the cell to the wall list.
  3. While there are walls in the list:
    1. Pick a random wall from the list. If the cell on the opposite side isn't in the maze yet:

      1. Make the wall a passage and mark the cell on the opposite side as part of the maze.
      2. Add the neighboring walls of the cell to the wall list.
    2. Remove the wall from the list.

It will usually be relatively easy to find the way to the starting cell, but hard to find the way anywhere else.

Note that simply running classical Prim's on a graph with random edge weights would create mazes stylistically identical to Kruskal's, because they are both minimal spanning tree algorithms. Instead, this algorithm introduces stylistic variation because the edges closer to the starting point have a lower effective weight.

我们将算法实现部分翻译成中文

  1. 让迷宫全都是墙.。
  2. 选一个格,作为迷宫的通路,然后把它的邻墙放入列表.。
  3. 当列表里还有墙时:
    1. 从列表里随机选一个墙,如果它对面的格子不是迷宫的通路:

      1. 把墙打通,让对面的格子成为迷宫的通路.。
      2. 把那个格子的邻墙加入列表。
    2. 如果对面的格子已经是通路了,那就从列表里移除这面墙。

简单研究算法实现过程我们可以发现,Prim算法就是不断地从所有可以是通路的位置中随意选一个挖洞,直到没有可能为通路的位置。

整个实现过程还是相当于随意为路线附权值的Prim算法。

下面我们来做C#下的代码实现:

/// <summary>
/// 普利姆迷宫生成法
/// </summary>
/// <param name="startX">起始点X坐标</param>
/// <param name="startY">起始点Y坐标</param>
/// <param name="widthLimit">迷宫宽度</param>
/// <param name="heightLimit">迷宫高度</param>
/// <param name="haveBorder">迷宫是否含有墙</param>
private int[,] Prim(int startX, int startY, int widthLimit, int heightLimit,bool haveBorder)
{//block:不可通行    unBlock:可通行const int block = 0,unBlock = 1;var r=new Random();//迷宫尺寸合法化if (widthLimit < 1)widthLimit = 1;if (heightLimit < 1)heightLimit = 1;//迷宫起点合法化if (startX < 0 || startX >= widthLimit)startX = r.Next(0, widthLimit);if (startY < 0 || startY >= heightLimit)startY = r.Next(0, heightLimit);//减去边框所占的格子if (!haveBorder){widthLimit--;heightLimit--;}//迷宫尺寸换算成带墙尺寸widthLimit *= 2;heightLimit *= 2;//迷宫起点换算成带墙起点startX *= 2;startY *= 2;if (haveBorder){startX++;startY++;}//产生空白迷宫var mazeMap = new int[widthLimit + 1, heightLimit + 1];for (int x = 0; x <= widthLimit; x++){//mazeMap.Add(new BitArray(heightLimit + 1));for (int y = 0; y <= heightLimit; y++){mazeMap[x, y] = block;}}//邻墙列表var blockPos = new List<int>();//将起点作为目标格int targetX = startX, targetY = startY;//将起点标记为通路mazeMap[targetX, targetY] = unBlock;//记录邻墙if (targetY > 1){blockPos.AddRange(new int[] { targetX, targetY - 1, 0 });}if (targetX < widthLimit){blockPos.AddRange(new int[] { targetX + 1, targetY, 1 });}if (targetY < heightLimit){blockPos.AddRange(new int[] { targetX, targetY + 1, 2 });}if (targetX > 1){blockPos.AddRange(new int[] { targetX - 1, targetY, 3 });}while (blockPos.Count > 0){//随机选一堵墙var blockIndex = r.Next(0, blockPos.Count / 3) * 3;//找到墙对面的墙if (blockPos[blockIndex + 2] == 0){targetX = blockPos[blockIndex];targetY = blockPos[blockIndex + 1] - 1;}else if (blockPos[blockIndex + 2] == 1){targetX = blockPos[blockIndex] + 1;targetY = blockPos[blockIndex + 1];}else if (blockPos[blockIndex + 2] == 2){targetX = blockPos[blockIndex];targetY = blockPos[blockIndex + 1] + 1;}else if (blockPos[blockIndex + 2] == 3){targetX = blockPos[blockIndex] - 1;targetY = blockPos[blockIndex + 1];}//如果目标格未连通if (mazeMap[targetX, targetY] == block){//联通目标格mazeMap[blockPos[blockIndex], blockPos[blockIndex + 1]] = unBlock;mazeMap[targetX, targetY] = unBlock;//添加目标格相邻格if (targetY > 1 && mazeMap[targetX, targetY - 1] == block && mazeMap[targetX, targetY - 2] == block){blockPos.AddRange(new int[] { targetX, targetY - 1, 0 });}if (targetX < widthLimit && mazeMap[targetX + 1, targetY] == block && mazeMap[targetX + 2, targetY] == block){blockPos.AddRange(new int[] { targetX + 1, targetY, 1 });}if (targetY < heightLimit && mazeMap[targetX, targetY + 1] == block && mazeMap[targetX, targetY + 2] == block){blockPos.AddRange(new int[] { targetX, targetY + 1, 2 });}if (targetX > 1 && mazeMap[targetX - 1, targetY] == block && mazeMap[targetX - 1, targetY] == block){blockPos.AddRange(new int[] { targetX - 1, targetY, 3 });}}blockPos.RemoveRange(blockIndex, 3);}return mazeMap;
}

转载于:https://www.cnblogs.com/WayneShao/p/5890379.html

[迷宫中的算法实践]迷宫生成算法——Prim算法相关推荐

  1. 【算法实践】搜狗信息流推荐算法交流.pdf(附下载链接)

    今天给大家带来搜狗科技王东先生所做的分享<搜狗信息流推荐算法交流.pdf>,本分享共包含如下四大部分: 1.推荐系统架构: 2.文章NLP: 3.召回算法: 4.个性化排序. 本PPT共2 ...

  2. 【数据结构】克鲁斯卡尔(Kruskal)算法 —PK— 普里姆(Prim)算法

    目录 一.克鲁斯卡尔(Kruskal)算法 二.普里姆(Prim)算法 三.两个算法对比 求图的最小生成树的典型算法: 克鲁斯卡尔(Kruskal)算法 普里姆(Prim)算法 注:考虑问题的出发点相 ...

  3. 浅谈最小生成树的算法思路(一)Prim算法

    Prim算法是求最小生成树的一种常见算法,简单谈一下笔者自己的理解. 算法思路 设已经确定的点集为P,初始为空.设还未确定的点集为Q,初始为该图所有点的集合.设已经确定的边为X,初始为空. 选取任意一 ...

  4. prim算法_求解最优树——Prim算法与Kruskal算法

    本文主要参考: 1.<Matlab数学建模算法全收录(数学建模比赛必备参考资料).pdf> 2.最小生成树-Prim算法和Kruskal算法 1 前言 简单来说,图由顶(就是结点)和边构成 ...

  5. c语言随机prim算法的迷宫生成,Prim算法生成迷宫

    初始化地图 function initMaze(r,c){ let row = new Array(2 * r + 1) for(let i = 0; i < row.length; i++){ ...

  6. 微博多尺度序列推荐算法实践

    今天给大家分享新浪微博机器学习算法专家谌贻荣博士在2021年全球机器学习ji s户大会上所做的分享<微博多尺度序列推荐算法实践.pdf>,关注推荐算法及其实践的伙伴们别错过啦!(到省时查报 ...

  7. 【实践】微博多尺度序列推荐算法实践.pdf(附下载链接)

    今天给大家分享新浪微博机器学习算法专家谌贻荣博士在2021年全球机器学习ji s户大会上所做的分享<微博多尺度序列推荐算法实践.pdf>,关注推荐算法及其实践的伙伴们别错过啦!(到#小程序 ...

  8. 【推荐实践】微博多尺度序列推荐算法实践.pdf(附下载链接)

    今天给大家分享新浪微博机器学习算法专家谌贻荣博士在2021年全球机器学习ji s户大会上所做的分享<微博多尺度序列推荐算法实践.pdf>,关注推荐算法及其实践的伙伴们别错过啦!(到#小程序 ...

  9. prim算法_数据结构与算法

    根据MOOC上课程总结,文章目录为: 一.引论 数据结构的基本概念 数据的逻辑结构和存储结构 算法及其时间复杂度 时间复杂度及应用 二.线性表 线性表的概念及顺序存储 单链表的概念及其基本操作 建立单 ...

最新文章

  1. java 静态方法 调用非静态方法_面试官:为什么java中静态方法不能调用非静态方法或变量?...
  2. C++ Websites
  3. shocked的歌曲 类似shell_Shell Shocked
  4. 白话算法(1) for循环不是随便写的
  5. Arcgis Javascript那些事儿(八)--图层获取与图层顺序
  6. r语言中删除向量的某些元素_R中的向量
  7. 翻译: 3.7. Softmax 回归的简明实现 pytorch
  8. 专业pdf转word转换软件 pdf转换器 pdf转txt pdf转ppt、excel
  9. 触摸屏查询软件1.8.4下载
  10. tomcat xml解析-digester
  11. [投资笔记]2016-11-25日
  12. 如何切换Echarts主题
  13. 掌舵9年,艾伦研究所创始CEO 光荣退休!他曾预言中国AI将领跑世界
  14. Taro,小程序scroll-view 填满剩下的高度空间,关闭页面回跳(部分ios机型 滚动不到底部)
  15. POJ1061-青蛙的约会【扩展欧几里得】
  16. 威联通ts-532x 篇五 qnap5.0 搭建服务器
  17. 每次访问某个界面,展示欢迎回来,并展示上次访问时间
  18. 未来dna计算机,DNA计算机领域重要进展:DNA模拟电路进行数学运算
  19. python练习-001
  20. java ffmpeg格式转换

热门文章

  1. 大二暑假周进度总结07
  2. Jenkins 基础入门
  3. lintcode-415-有效回文串
  4. IOS学习之UINavigationController详解与使用(一)添加UIBarButtonItem
  5. Java,想说爱你真不容易
  6. 应用名称本地化/国际化
  7. Ubuntu 开发环境搭建
  8. Python2.x自学笔记(一)——Json格式与请求
  9. 时间复杂度和空间复杂度的故事
  10. JAVA 面向对象-2-继承(Inheritance)