我正在使用游戏提供的API为RTS游戏编写AI。我想要做的一件事是确定一组绑定敌国的线段,但是,游戏只提供一个函数,它告诉我单个2D点区域的teamID。
对游戏AI的查询执行起来非常昂贵,因此我需要将查询数量保持在绝对最小值,即使这意味着偶尔会得到质量稍差的答案。高估敌人领土面积也比低估它更好。
如何使用最少数量的查询有效地确定非凸空间区域周围的一组边界线?
Nb:用Lua写的答案的奖励积分,但伪码也很好。
答案 0 :(得分:3)
您可能正在寻找一组点周围的凸包,请参阅:http://en.wikipedia.org/wiki/Convex_hull
这是一个O(n log n)问题 - 计算上也不算太糟糕。对于某些伪代码,请参阅:http://en.wikipedia.org/wiki/Graham_scan
编辑:有了你澄清的问题,我知道这些区域不一定是凸面的,所以凸面船体会给你一个比你想要的更广阔的区域。但是,它可能是你可以改进的起点(因为你正在寻找的最终非凸区域)。
更多编辑:如果您真的只有查询单个点的功能,那么您的问题与矢量化位图图像相同。每个点都是“像素”,敌人区域是“像素”的(近似)矢量化。
答案 1 :(得分:2)
我建议你使用蒙特卡罗方法来接近它
http://en.wikipedia.org/wiki/Monte_Carlo_method
从一组已知点开始应该可以根据您的目标知识和初始点的结果(作为起始城市的集合)来改进额外的“随机”猜测
我可能会考虑尝试一些类似于已知点之间的等势线的东西,用假定的点大小加权。错误地认为早期附着的岛屿将极大地影响这些猜测,但需要更多思考。
修改强>
所以我和一位朋友进行了交谈,他做了地图分析,用于从坐姿/航拍图像中找到特定植被的跨度......这个问题与此问题有些相关,因为她试图在自己查看地图之前自动定位补丁。
她说,典型的方法是应用网格模式,细分整个区域,并在找到特定模式时收缩。因此,您需要对常规网格进行采样(设计此网格可能包含您正在寻找的一些尺寸知识),如果您获得了一个匹配,请在该区域中进行更多样本...如果不这样做,则抵消网格并重新样品
这种方法的优化在于人类对搜索模式的了解。例如,您可以根据对大小/形状的常见期望来指定搜索网格中的细分数。
答案 2 :(得分:2)
我假设你可以在领土内的空间找到一个点。称之为Z.(因为你有几个城市,你可以选择一个平均的城市位置作为中心位置。)
考虑到起点Z,我考虑做的是从该点向外生成一组光线,每条光线的大小都有下限和上限,并且数量增加以获得细节。我在下面草拟了一个方案。没有关于它的测试;随时建议改进。
每条光线由角度Theta表示,并且具有原点Z.而不是一个长度,每条光线具有两个相关的长度,内部和外部,我们将尝试收敛。 Inside的初始值设置为0,外部设置为大于任何可能区域半径的值(“Horizon”);我们会收缩外面,直到它在境内,然后在内部生长,直到它不在境外,使用二分搜索(游戏空间直径为log2 N)。我们还将增加光线的数量,因为终点扩散以获取领土边界细节。最终的结果应该是一组光线,它们在领土周围建立一个边界,其端点不超过“间距”。
您可以从一条光线开始(theta = North(0),Inside = 0,Outside = Horizon)。 让我们调用一组光线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
运行成本应该是最大区域直径的log 2,乘数必须与区域的周长除以所选的光线终点间距。
这个方案并不完美;它将在半岛存在的情况下失败,因为在半岛范围内没有采样,射线恰好穿过该半岛。如果半岛任意薄,那么需要任意多的样本才能发现它们。你也许可以选择一个半岛的最小宽度,然后调整算法,当它最终找到一个会聚光线时向外走,在半岛宽度上确保它没有傻瓜。