【问题标题】:Efficiently determining the bounds of a set有效地确定集合的边界
【发布时间】:2011-06-20 21:29:21
【问题描述】:

我正在使用游戏提供的 API 为 RTS 游戏编写 AI。我想做的一件事是确定一组以敌国为界的线段,但是,游戏只提供了一个函数,告诉我单个 2D 领土点的团队 ID。

对游戏 AI 的查询执行起来非常昂贵,因此我需要将查询数量保持在绝对最低限度,即使这意味着偶尔会得到质量稍差的答案。高估敌方领土面积也比低估它好。

如何使用最少的查询有效地确定围绕非凸空间区域的一组边界线?

Nb:用 Lua 写的答案加分,但伪代码也可以。

【问题讨论】:

  • 领土可以是任何多边形还是以特定形状的瓷砖命名?您是否有任何关于从哪里开始寻找的信息,或者您只是查询有限的 2D 空间来寻找它?
  • 它们可以是任何形状。在此处查看默认地图上的大陆轮廓:store.introversion.co.uk/images/screen_shots/defcon_screen1.jpg
  • 我知道几个起点,因为我可以得到所有敌方城市的位置。所以假设你从已知在敌方领土内的大约 20 个点开始。
  • 区域有最大尺寸吗?
  • 没有最大尺寸,超过整个世界的尺寸。世界在 x 的范围内

标签: language-agnostic math geometry computer-science set


【解决方案1】:

您可能正在寻找一组点周围的凸包,请参阅:http://en.wikipedia.org/wiki/Convex_hull

这是一个 O(n log n) 问题——在计算上还不错。部分伪代码见:http://en.wikipedia.org/wiki/Graham_scan

编辑:根据您的澄清问题,我了解这些区域不一定是凸的,因此凸包将为您提供比您正在寻找的更广泛的区域。但是,它可能是您可以细化的起点(因为您要寻找的最终非凸区域位于船体内部)。

更多编辑:如果你真的只有一个查询单点的功能,那么你的问题与矢量化位图图像相同。每个点都是一个“像素”,敌人区域是“像素”的(近似)矢量化。

【讨论】:

  • 抱歉,在我的回答中我说的是非凹的,我的意思是非凸的。敌方领土绝对不是凸包。另外,我不确定标准的凸包算法是否可行,因为它们假设访问点很便宜,而对我来说,问题实际上是确定要查询哪些(最少数量)点。
  • OP 不是在寻找如何找到凸包。他正在寻找定位多边形边界点的最佳方法
  • 嗯,凸包找到边界点(即多边形)位置的最佳方法,但他澄清说它不一定是凸包。这使它更有趣。嗯.
  • 我同意凸包可能是一个很好的起点。但我认为我不能以有效的方式确定凸包。像 graham scan 这样的算法谈论找到具有最大 y 的点,然后对所有点进行分类,直到找到具有最大 x 的点,依此类推。由于点位于真实空间中,因此我要查询的点数是无限的!我需要一种算法,它不仅可以从点集确定凹壳,还可以确定查询的最佳位置以生成这些点。
  • 凸包可能是一个很好的起点,可以将搜索区域最小化到区域的实际边界,但在这种情况下它不起作用。凸包计算意味着一组已知点。手头的任务是通过有根据的猜测来最佳地定位边界。
【解决方案2】:

我建议你使用蒙特卡罗方法来处理它

http://en.wikipedia.org/wiki/Monte_Carlo_method

从一组已知点开始应该能够根据对目标的了解和初始点的结果(作为一组起始城市)改进额外的“随机”猜测

我可能会考虑尝试类似于已知点之间的等势线,由假定的点大小加权。被错误地认为是早期附着的岛屿将极大地影响这些猜测......需要更多考虑。

编辑:

因此,我与一位为从卫星/航空图像中定位特定植被跨度进行地图分析的朋友进行了交谈……这与这个问题有些相关,因为她尝试在自己查看地图之前自动定位斑块。

她说,典型的方法是应用网格图案,细分您的总面积并在找到特定图案时缩小自身。因此,您将对常规网格进行采样(设计此网格可能包括您正在寻找的尺寸的一些知识),如果您受到打击,请在该区域进行更多采样......如果您不这样做,请偏移您的网格并重新 -样本。

这种方法的优化在于人类对您的搜索模式的了解。例如,您可以根据对大小/形状的共同期望来指定搜索网格中的细分数量。

【讨论】:

  • 你当然需要抽样,是的,你可以在城市周围抽样。但是您需要一些东西来相对快速地有效覆盖任意大块区域,否则您的成本将 area_of_territory (N^2) 除以样本量(小常数)。
【解决方案3】:

我假设您可以在领土内的空间中找到 a 点。称之为 Z。(由于您有多个城市,您可以选择一个平均城市位置作为中心。)

给定起点 Z,我会考虑从该点向外生成一组射线,每条射线的大小都有上下界,并且该组的数量会增加以获取细节。我在下面画了一个方案。没有任何关于它的测试;随时提出改进建议。

每条光线由角度 Theta 表示,并有一个原点 Z。每条光线不是一个长度,而是有两个相关的长度,内部和外部,我们将尝试收敛它们。 Inside 的初始值设置为 0,outside 的初始值设置为大于任何可能区域(“Horizo​​n”)的半径;我们将使用二分搜索(在您的游戏空间的直径中的 log2 N )缩小外部直到它在区域内,并在内部增长直到它不是完全在区域之外。随着端点散开以获取领土边界细节,我们还将增加光线的数量。最终结果应该是一组光线,它们在区域周围建立一个边界,其端点仅“间隔”开。

您可以只从一条光线开始(theta=North(0),Inside=0,Outside=Horizo​​n)。 让我们将光线集合称为 R。我们假设光线集合 R 按 theta 排序, 如果我们有来自 R 的射线 r,则 next(r) 是排序集中的下一条射线, 用 next(r) 表示 R 中的最后一条射线是集合中的第一条射线。自从 如果您知道城市位置,您可能会使用以城市为内点的光线播种该集合。 无论哪种方式,它都应该工作。

附加参数“阈值”为您提供答案的精确程度。

R = empty
add_to_R(0,0,Horizon)
repeat until done
    done = true
     for each ray r in R
      guess = average(Inside(r),Outside(r))
      if guess>threshold
         then done = false
      if interritory(Z+(Theta(r),guess))
        then Inside(r)=guess
        else Outside(r)=guess
     for each ray r in R
       if (distance(Inside(r),Inside(next(r)))> spacing
          then add_to_R(average(Theta(r),Theta(next(r)),
                        min(Inside(r),Inside(next(r)),
                        max(Outside(r),Outside(next(r))
end

运行成本应为最大区域直径的对数 2,乘数与区域周长除以所选光线端点间距有关。

这个方案并不完美;如果没有在半岛内采样,光线恰好穿过该领土的半岛,它将失败。如果半岛任意薄,发现它们需要任意多的样本。你也许可以选择一个半岛的最小宽度,然后调整算法,当它最终找到一条会聚的光线时,以半岛的宽度向外走,以确保它没有出错。

【讨论】:

  • 我自己想到(并实施)了一个有点像这样的方案。它工作得很好,我开始怀疑它可能是最好的解决方案!
  • 令我震惊的是,另一种方法是在图形世界中对不规则形状进行所谓的“泛滥”。我没看过,当然可以逐个像素地进行泛洪,但是通过使用连续的大矩形(例如,每次成功尝试双倍)作为最后一个成功泛洪点附近的样本来泛洪是有意义的。
  • 像往常一样,维基百科很有帮助:en.wikipedia.org/wiki/Flood_fill 那里描述了很好的泛洪算法,包括提到存储你想要的区域边界。他们都没有做我的样本更大的矩形建议;他们假设可以廉价访问您声称没有的像素。不过我想知道;每场比赛你只需要确定一次国家形态...你确定这行不通吗?
猜你喜欢
  • 1970-01-01
  • 2021-12-05
  • 2017-03-03
  • 1970-01-01
  • 2013-10-05
  • 2010-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多