需要移动多少步才能到达目的地?高效注水

2024-01-04

我想通过四向移动的次数来计算单元格与目标单元格的距离以到达某处。因此,紧邻目的地的四个单元格的距离为 1,每个单元格的四个基本方向上的单元格的距离为 2,依此类推。最大距离可能约为 16 或 20,并且有些单元格被障碍物占据;距离可以绕过它们,但不能穿过它们。

我想将输出存储到二维数组中,并且我希望能够非常快速地计算更大迷宫地图上任何目的地的“距离图”。

我通过洪水填充的变体成功地做到了这一点,其中我将相邻未填充单元格的增量距离放入优先级队列中(使用 C++ STL)。

我对这个功能很满意,现在想专注于优化代码,因为它对性能非常敏感。

可能会有什么狡猾而快速的方法呢?


我认为你做的一切都是对的。如果您编码正确,则需要O(n)时间和O(n)用于计算洪水填充的内存,其中n是细胞的数量,可以证明不可能做得更好(一般情况下)。填写完成后,您只需返回任何目的地的距离即可O(1),很容易看出它还可以做得更好。

所以如果你想优化性能,你只能关注代码局部优化。这不会影响渐近复杂度,但可以显着提高实际执行时间。但在没有实际查看源代码的情况下,很难给你任何代码优化的建议。

因此,如果您确实想查看优化的代码,请参阅以下内容(纯 C):

#include <stdlib.h>

int* BFS()
{
    int N, M; // Assume we have NxM grid.
    int X, Y; // Start position. X, Y are unit based.
    int i, j;
    int movex[4] = {0, 0, 1, -1}; // Move on x dimension.
    int movey[4] = {1, -1, 0, 0}; // Move on y dimension.
    
    // TO DO: Read N, M, X, Y
    
    // To reduce redundant functions calls and memory reallocation 
    // allocate all needed memory once and use a simple arrays.
    int* map = (int*)malloc((N + 2) * (M + 2) * sizeof(int)); 
    int leadDim = M + 2;
    // Our map. We use one dimension array. map[x][y] = map[leadDim * x + y];
    // If (x,y) is occupied then map[leadDim*x + y] = -1;
    // If (x,y) is not visited map[leadDim*x + y] = -2;

    int* queue = (int*)malloc(N * M * sizeof(int));
    int first = 0, last =1; 
    
    // Fill the boarders to simplify the code and reduce conditions
    for (i = 0; i < N+2; ++i)
    {
        map[i * leadDim + 0] = -1;
        map[i * leadDim + M + 1] = -1;
    }
    
    for (j = 0; j < M+2; ++j)
    {
        map[j] = -1;
        map[(N + 1) * leadDim + j] = -1;
    }
    
    // TO DO: Read the map.
    
    queue[first] = (X+1) * leadDim + Y + 1;
    map[(X+1) * leadDim + Y + 1] = 0;
    
    // Very simple optimized process loop.
    while (first < last) 
    {
        int current = queue[first];
        int step = map[current];
    
        for (i = 0; i < 4; ++i)
        {
            int temp = current + movex[i] * leadDim + movey[i];
            if (map[temp] == -2) // only one condition in internal loop.
            {
                map[temp] = step + 1;
                queue[last++] = temp;
            }
        }
    
        ++first;
    }
    
    free(queue);
    
    return map;
}

该代码可能看起来很棘手。当然,它不是面向对象(OOP)的,但如果您想要真正快速的东西,那就是您所需要的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

需要移动多少步才能到达目的地?高效注水 的相关文章

  • Codility 钉板

    尝试了解 Codility NailingPlanks 的解决方案 问题链接 https app codility com programmers lessons 14 binary search algorithm nailing pla
  • 检索受“rowspan”影响的行的列索引的最有效方法是什么?

    考虑下表 table thead tr th th th A th th B th th C th tr thead tbody tr th 1 th td Apples td td Oranges td td Pears td tr tb
  • 如何从一组重叠的圆计算多边形集?

    这个问题是一些计算细节的扩展这个问题 https stackoverflow com questions 1667310 combined area of overlapping circles 假设有一组 可能重叠的 圆 并且希望计算这组
  • 快速搜索压缩文本文件

    我需要能够在大量压缩文件 txt 中搜索文本 压缩可能会改变为其他东西 甚至成为专有的 我想避免解压所有文件并压缩 编码 搜索字符串并在压缩文件中搜索 这应该可以通过对所有文件使用相同的码本使用霍夫曼压缩来实现 我不想重新发明轮子 所以 任
  • 如何将一组重叠范围划分为不重叠范围?

    假设您有一组范围 0 100 一 0 75 b 95 150 c 120 130 d 显然 这些范围在某些点上重叠 您将如何剖析这些范围以生成不重叠范围的列表 同时保留与其原始范围相关的信息 在本例中为范围后面的字母 例如 运行算法后的上述
  • 点集子集的最小周长凸包

    给定平面上的 n 个点 没有 3 个共线 给定数字 k 找到 k 个点的子集 使得 k 个点的凸包在 k 个点的子集的任何凸包中具有最小周长 我可以想到一个简单的方法 运行时间为 O n k k log k 找到大小为 k 的每个子集的凸包
  • 解释一下从 N 个给定集合中的每一个中给出第 K 个最大数字的示例?

    今天我尝试解决一个Facebook 编程挑战赛 https facebook interviewstreet com recruit challenges 我遇到的挑战是 酒吧问题 可以找到here https github com alo
  • 包围一组点的多边形

    我有一组 S 点 2D 由 x 和 y 定义 我想找到 P 包围该组所有点的最小 含义 具有最少数量的点 多边形 P 是S 有没有已知的算法来计算这个 我在这个领域缺乏文化令人惊讶 感谢您的帮助 对于这个问题有很多算法 它被称为 最小边界框
  • 使用并集查找(又名不相交集)检测图是否是二分图

    我正在 Spoj 上做一个问题 基本上可以简化为检测图是否是二分图 我正在尝试使用 dfs 为图表着色 但它太慢了 有人评论这个 没有 bfs 没有 dfs 没有二部图 简单的并查集就可以做到 确实速度很快 提示 1 偶数长度的环不会影响两
  • C# 中的 strstr() 等效项

    我有两个byte 我想找到第二个的第一次出现byte 在第一个byte 或其中的一个范围 我不想使用字符串来提高效率 翻译第一个byte to a string会效率低下 基本上我相信就是这样strstr 在 C 中做 最好的方法是什么 这
  • 直接选择排序与交换选择排序

    有什么区别直接选择排序 vs 交换选择排序 今天我陷入了一场争论 我的教授在他的讲义中使用了这两个术语 维基百科和任何教科书或网站都会为您提供的选择排序就是他所说的 交换选择排序 我以前从未听说过 交换选择排序 这个术语 仅 选择排序 并且
  • 数学组合的完美最小哈希

    首先定义两个整数N and K where N gt K 两者都在编译时已知 例如 N 8 and K 3 接下来 定义一组整数 0 N or 1 N 如果这使答案更简单 并调用它S 例如 0 1 2 3 4 5 6 7 的子集数量S wi
  • shell脚本中关联数组的时间复杂度

    我想知道在 shell 脚本中使用关联数组时如何构造 实现 另外 我想知道基于 shell 脚本的关联数组的时间复杂度是否是最佳的 因为我们可以使用字母和数字作为它们各自的键 编辑 他们使用什么哈希函数 如果您使用关联数组 则不能通过 使用
  • 在 2D int 向量上使用 std::fill

    我试图将 2D 向量中所有元素的值设置为特定值 据我所知 不能像将 memset 用于数组那样将其用于向量 因此 我必须使用 std fill 将 2D 向量中的所有元素设置为特定值 但是 我知道如何对一维向量使用填充 如下所示 vecto
  • Florian 的 Grisu2 算法如何工作?

    我遇到了一个关于将 double 转换为 ascii 的问题 经过搜索 我得到了 Florian 的论文 使用整数快速准确地打印浮点数 http www cs tufts edu nr cs257 archive florian loits
  • 用于开始和/或包含搜索的最快字符串集合结构/算法是什么

    我有以下情况 我有一个大的字符串集合 比如说 250 000 平均长度可能是 30 我要做的就是在这些搜索中进行许多搜索 大多数搜索都是 StartsWith 和 Contains 类型的 该集合在运行时是静态的 这意味着选择的集合的初始读
  • 在java中使用BUBBLE SORT对二维字符串数组进行排序

    类似的问题已经被问过 但从来没有关于二维字符串数组 因此在尝试了很长时间之后我找不到我想要的 我正在尝试使用 BubbleSort 对 java 中的 2D 字符串数组进行排序 作为输入 我收到一个二维字符串数组 一个表 以及您应该排序的
  • 每个术语出现的次数

    我得到了一个数组a n 2 where n can be 10 5最大时有n个科目和n个学生 全部编号为 1 2 n a i 0 and a i 1 1 lt i lt n 表示在第 i 个科目中 所有来自a i 0 to a i 1 通过
  • 动态规划 (DP) 中的重叠子问题是什么?

    为了使动态规划适用 问题必须具有两个关键属性 最优子结构 and 重叠子问题 1 https en wikipedia org wiki Dynamic programming 对于这个问题 我们只关注后一个属性 有各种不同的定义重叠子问题
  • 高效列出目录中的所有子目录

    请参阅迄今为止所采取的建议的编辑 我正在尝试使用 WinAPI 和 C 列出给定目录中的所有目录 文件夹 现在我的算法又慢又低效 使用 FindFirstFileEx 打开我正在搜索的文件夹 然后我查看目录中的每个文件 使用 FindNex

随机推荐

  • Google“reCaptcha”有时不会显示/渲染

    有时我必须多次重新加载网页 直到呈现 reCaptcha 我和一个朋友在 Firefox 和 Chrome 上进行了测试 但问题是一致的 并且似乎并不取决于所使用的浏览器 我用来显示 reCaptcha 的代码
  • Java归并排序,“合并”步骤应该用队列还是数组来完成?

    这不是家庭作业 我没有钱上学 所以我一边在高速公路收费站轮班工作一边自学 漫长的夜晚 几乎没有顾客 我试图通过以下方式实现一个简单的 合并排序 thinking首先 如果你想进行一些实际的学习 请稍微伸展一下我的大脑 并且then查看我正在
  • Php 数组对动态数组上的服装尺寸 (XXS XS S M L XL XXL) 和数字进行排序

    我有一个类似这样的数组 Array 0 gt XL 1 gt M 2 gt L 3 gt XL 4 gt S 5 gt XXL 但我想对我的数组进行排序 S M L XL XXL 我知道我可以用 usort 来做到这一点 但是 我得到了一些
  • 为什么“with open()”更适合在 Python 中打开文件?

    通常 当有人发布他们的代码时 人们会在旁边添加 你应该使用with open filename as f现在的语法 我同意大多数老式的f open 陈述没有附带 close 我什至回答过一些问题 其中对 隐式关闭 的依赖是他们编程问题的全部
  • Matlab 软件中的“处理”会减慢程序速度

    每当我保存 更改文件夹或有时看似随机的时间时 当前文件夹图块都会显示一个加载图标并显示 正在处理 我总是必须按 取消 否则 Matlab 软件会变慢或冻结 我的编程课上似乎没有其他人对此有问题 我正在使用 MATLAB R2015b 我可以
  • DocumentDb:没有索引的查询

    当从索引中排除所有路径时 为什么我仍然能够对 ID 以外的字段执行成功的查询 排除所有路径 collection IndexingPolicy ExcludedPaths Add new ExcludedPath Path Query SE
  • 如何从 GCM 获取 Canonical ID

    我正在尝试为我的设备获取唯一的 ID 以便我可以从我的服务器获取推送通知 正如所有教程所说 我使用 GMC 注册 GoogleCloudMessaging gcm GoogleCloudMessaging getInstance conte
  • 数组引用绑定与使用模板的数组到指针转换

    由于重载解析不明确 此代码示例无法编译 void g char t 4 void g char t int main char a 123 g a 仔细阅读重载解析规则可以清楚为什么失败 这里没有问题 如果我们正式将其改造为模板版本 tem
  • 使用IntelliJ作为git mergetool总是一启动就退出

    我已经将 IntelliJ 配置为我的 mac 上的 diff 和 mergetool 但是 git 启动它 命令行总是立即返回 而不是等待 diff 完成 这意味着所执行的更改不会反映在磁盘上 我的配置是 mergetool intell
  • 如何在 MigLayout 中获得一个向右对齐的按钮

    我正在使用 Miglayout 向面板添加一个按钮 并尝试我可能做的事情 但我无法让它转到面板的右端 它坚持向左齐平 奇怪的是 该演示在示例中有点简短 它仅在同一面板上的其他按钮的上下文中显示它 我有一个这样的面板 dialog gt co
  • 如何在 Core Graphics / Quartz 2D 中绘制圆角矩形?

    我需要绘制圆角矩形的轮廓 我知道我可以制作直线和圆弧 但也许还有圆角矩形的功能 您可以使用 UIBezierPath bezierPathWithRoundedRect cornerRadius or UIBezierPath bezier
  • unity3d 和 git 子模块可能吗?

    太长了 这将是一篇冗长的文章 但我相信许多 unity3d 开发人员也遇到了和我一样的问题 这个问题需要一个明确 一劳永逸的答案来拯救我们的集体理智 所以在过去的两年多里我一直在使用 git 但我并没有深入研究它 我可以从 bitbucke
  • UISearchBar inputAccessoryView

    The UISearchBar似乎有inputAccessoryView as a readOnly财产 如何使用我自己的 customToolbar 设置它 Edit 正如下面的评论中提到的 这不再是 iOS 6 后的问题 请参阅UISe
  • 流式传输 okhttp 响应正文

    我正在实施一个服务器发送的事件 http www w3schools com html html5 serversentevents asp使用 OkHttp 的库 服务器发送事件的工作原理是与服务器保持开放的 HTTP 连接 在服务器上
  • C++ 迭代具有混合字符长度的 utf-8 字符串

    我需要循环 utf 8 字符串并获取该字符串的每个字符 字符串中可能有不同类型的字符 例如一字节长度的数字 三字节长度的汉字等 我看了这个post https stackoverflow com questions 2852895 c it
  • git reset --soft 并返回到最新的提交

    所以我只是做了一个 git reset soft 来返回到之前的提交 现在 如果我想返回到之前的最新提交该怎么办 即 最新的提交 我尝试执行 git log 但那里列出的提交没有最新的提交 git reset如果您只想返回并查看旧的提交 那
  • 如果使用 Debug dll,服务不会及时响应启动或控制请求

    我试图在我的计算机上部署 Windows 服务 但是当我尝试启动它时出现以下错误 Windows 无法在本地计算机上启动 myService 错误 1053 该服务未及时响应启动或控制请求 经过一番研究后 我发现我正在使用 调试 选项来编译
  • java中将十六进制数字字符串转换为双精度数字

    java中如何将十六进制数字字符串转换为双精度数字 在 matlab 中很简单 gt gt hex2num c0399999a0000000 ans 25 6000 但我也可以在java中做同样的事情吗 我尝试了 parseInt 但这个数
  • 检测 Control.KeyUp 事件上的 Alt 键时出现问题

    我有一个带有 KeyDown 和 KeyUp 事件的控件 如下所示 我遇到的问题是 x 在 KeyDown 中为 TRUE 但在 KeyUp 中始终为 FALSE 我正在尝试检测 Alt 键 正如您可能已经猜到的那样 有什么我不知道的问题吗
  • 需要移动多少步才能到达目的地?高效注水

    我想通过四向移动的次数来计算单元格与目标单元格的距离以到达某处 因此 紧邻目的地的四个单元格的距离为 1 每个单元格的四个基本方向上的单元格的距离为 2 依此类推 最大距离可能约为 16 或 20 并且有些单元格被障碍物占据 距离可以绕过它