【发布时间】:2014-01-16 02:15:59
【问题描述】:
我的作业是这样的:
给你一张由四种颜色的像素组成的图像。颜色对应于地形、敌人、盟友和墙壁。可以在任何坐标(一对整数)处投下炸弹。还给你:
r- 炸弹的作用半径(以像素为单位,正整数)e- 杀死一个敌人的点数a- 杀死一个盟友的点数(例如
r = 10、e = 1、a = -2)当炸弹被投下时,半径(欧几里得距离)内的所有敌人和盟友都会被杀死,除非他们和炸弹之间有墙(即连接炸弹的士兵的非抗锯齿线穿过墙壁)。当炸弹落在墙上时,这个特定像素的行为就像正常地形一样。墙的其余部分仍然是墙。
你从 0 分开始。找到你应该投下一颗炸弹的坐标以获得最好的分数。如果有多个最优解,则返回其中任何一个。
这是一个示例图片,经过裁剪、调整大小并更改了颜色以提高可读性:
我得到的原图可以在here找到。
我已经解决的问题
我知道暴力破解这个问题是一个糟糕的解决方案。我想出了一个想法,如何在没有墙壁的情况下快速解决它。这是一些伪代码:
args Map, R, A, E
for (every Soldier)
create a Heightmap with dimensions of Map
zero-fill the Heightmap
on the Heightmap draw a filled circle of value 1 around Soldier with radius R
if (Soldier is Ally)
multiply Heightmap by A
else
multiply Heightmap by E
add all Heightmaps together
return coordinates of highest point in TotalHeightmap
当然这个'sn-p'是可以优化的,但是这种形式更容易理解。通过用墙壁约束高度图圆圈,可以将其扩展到完整的解决方案。画圆很简单,许多图像处理库都提供了这样做的函数,所以画圆可能是个好主意,然后在上面画墙,然后从中心填充圆,停在墙或圆的边界上。我会在实施时检查性能。
如果没有约束圈,我会这样做:
run the above code to get a TotalHeightmap
create empty PointList
for (every Point in TotalHeightmap)
create PointObject with properties:
Coordinates,
Height,
WallsFlag = False
add PointObject to PointList
sort PointList by descending Height
until (PointList[0].WallsFlag == True)
for (every Soldier in radius R from PointList[0])
if (Bresenham line connecting Soldier with PointList[0] intersects a Wall)
subtract (A if Soldier is Ally else E) from PointList[0].Height
set PointList[0].WallsFlag = True
sort PointList by descending Height
return PointList[0].Coordinates
只要敌人和盟友的分数都不是负数,它就会起作用,所以它远非完美。为了解决这个问题,我可以遍历所有像素,但这会非常慢(我猜,它不像暴力破解那么慢,但这听起来不是一个好主意)。寻找墙壁交叉点的方法似乎也很粗糙。
我正在寻找一个更优雅和快速的解决方案来解决这个问题。你会怎么解决?如果有帮助,我将在 Python 中使用 PIL 实现它。
顺便说一句,我相信我的老师同意我在 SO 上发布这个问题,我相信他甚至希望我讨论它并实施最佳解决方案。
【问题讨论】:
-
是什么让您认为分配高度图、相乘和相加比简单的暴力破解更快?另外,slow的定义是什么?只有相对于更快的替代方案,事情才会变得缓慢。你的硬件速度慢吗?你甚至对速度有限制吗?在这项任务中有这么多条件,可能没有什么比蛮力更精确和可靠了。
-
@Haroogan 正如我所说,我知道它可以优化。高度图只是解释我的算法的好方法。我的老师说它必须足够快,以平均笔记本电脑在一分钟内解决example map。即使使用蛮力方法也应该可以实现,但我就是无法忍受粗鲁、盲目的解决方案。我正在寻求一个很好的、优雅的算法来解决这个问题或关于如何改进我的解决方案的建议。
-
太多不可预测的情况。墙可以有任何几何形状。您将不得不蛮力进行:测试每个像素周围半径范围内敌人的存在,并将来自敌人/盟友的射线发射到该像素,以找出与墙壁的交叉点(如果有的话)以拒绝它们。这似乎是获得可靠结果的唯一方法。而且恐怕没有典型的数学理论能够以优雅的方式解决这个问题。将其视为光线追踪,这是纯粹的蛮力(除了优化)。
-
这个任务的一个优点是它可以很容易地被并行化。例如,您可以简单地将 OpenMP 用于循环。或者,您可以使用所需的模式手动细分域,并在单独的线程中运行每个子域的处理(正是 OpenMP 对循环所做的事情,但麻烦较少)。您可以这样做,因为每个测试的结果不相互依赖,从这个意义上说,任务非常简单。例如,任何现代 GPU 都绝对会完成这项任务。只需为您的利益使用硬件,您就赢了。
-
这听起来很棒codegolf
标签: algorithm language-agnostic