问题是由附件连接的建筑物组成的迷宫。迷宫的布局完全为程序员所知。但是,每个附件都填充了四种有毒气体中的一种。可提供防毒面具,可以提供各种气体的免疫力,前提是它配有专门针对该类型气体的过滤器。四个过滤器(每种类型中的一个)都位于迷宫中的给定建筑物中。
a)第一个目标是编写一个方法maze_solver_single_explorer(maze, start, end)
,它返回从end
到达start
所需的最小时间步数。在每个时间步长期间,可以拾取位于同一建筑物中的任意数量的过滤器,然后最多遍历一个附件(假设拥有适当的过滤器)。从气体罩上安装或拆卸过滤器可以根据需要立即进行。
b)第二个目标是编写一个方法maze_solver_multiple_explorers(maze, start, end, max_timesteps)
,该方法返回在给定时间限制内从end
到达start
所需的最小探索者数量(小于20)。探险者从源头建筑开始,只有一个探险家需要到达目标建筑。除了上述规则之外,还可以删除其他玩家从同一建筑物中取出的过滤器。丢弃一个或多个过滤器可以在时间步的开始时完成,以便资源管理器可以删除过滤器并在同一时间步中探索附件。但是,另一个浏览器可能无法选择在同一时间步长中丢弃的过滤器。示例:explorer 0向左移动以获取过滤器0,同时资源管理器1向右移动以获取过滤器1.然后两者都返回源构建器并且资源管理器0选择由资源管理器1删除的过滤器1并继续前往目的地建筑。
如何在Python中对此问题进行建模/编码?
编辑:我写了一些简单的测试用例:def test_explore_single_basic(self):
buildings = ['A', 'B', 'C', 'D']
annexes = [('A', 'B', 0), ('B', 'D', 2), ('B', 'C', 0), ('C', 'D', 3)]
filters = [('A', 0), ('C', 2), ('D', 3), ('D', 1)]
start = 'A'
goal = 'D'
labyrinth = Maze(buildings, annexes, filters, start, goal)
# There are two edges leading to the goal building, D. However the
# filter of type 3 cannot be obtained without reaching the goal
# building itself. So the explorer must first go to C to pick up the
# filter of type 2. Thus the fastest sequence of actions is:
# pick up filter 0, go from A to B, go from B to C, pick up filter 2,
# go from C to B, go from B to D.
self.assertEqual(maze_solver_single_explorer(maze), 4)
def test_explore_single_unreachable(self):
# Same as the previous test, except we require filter type 3 to go
# from B to D.
buildings = ['A', 'B', 'C', 'D']
annexes = [('A', 'B', 0), ('B', 'D', 3), ('B', 'C', 0), ('C', 'D', 3)]
filters = [('A', 0), ('C', 2), ('D', 3), ('D', 1)]
start = 'A'
goal = 'D'
maze = Maze(buildings, annexes, filters, start, goal)
self.assertEqual(maze_solver_single_explorer(maze), None)
def test_explore_multiple_basic(self):
# L -- S -- R
# |
# D
# |
# G
buildings = ['S', 'L', 'R', 'D', 'G']
annexes = [('S', 'L', 0), ('S', 'R', 1), ('S', 'D', 2), ('D', 'G', 3)]
filters = [('S', 0), ('S', 1), ('R', 2), ('L', 3)]
start = 'S'
goal = 'G'
maze = Maze(buildings, annexes, filters, start, goal)
# A single explorer needs 6 timesteps to get to the goal.
self.assertEqual(maze_solver_multiple_explorers(maze, 20), 1)
self.assertEqual(maze_solver_multiple_explorers(maze, 6), 1)
# Two explorers can make it in 5 timesteps. One explorer goes right,
# picks up filter 2, goes back and drops it at S.
# Meanwhile, the other explorer goes left, picks up filter 3, goes
# back to S, picks up filter 2, and finally proceeds to D and G.
self.assertEqual(maze_solver_multiple_explorers(maze, 5), 2)
# No matter how many explorers you have, it's not possible to reach
# the goal in 4 or fewer timesteps.
self.assertEqual(maze_solver_multiple_explorers(maze, 4), None)
def test_explore_multiple_unreachable(self):
# Same as the previous test, except filter type 2 is unreachable.
buildings = ['S', 'L', 'R', 'D', 'G']
annexes = [('S', 'L', 0), ('S', 'R', 1), ('S', 'D', 2), ('D', 'G', 3)]
filters = [('S', 0), ('S', 1), ('D', 2), ('L', 3)]
start = 'S'
goal = 'G'
maze = Maze(buildings, annexes, filters, start, goal)
self.assertEqual(maze_solver_multiple_explorers(maze, 18), None)
答案 0 :(得分:0)
Dijkstra的算法是一种很好的方法。但是,您需要使状态表示更完整。除了对资源管理器的位置进行建模之外,您还需要对资源管理器所承载的过滤器进行建模。
例如,你从位置开始:
{x: 0, y: 0, filters: []}
您可能采取的行动是:
['left', 'right', 'up', 'down']
,(假设所有路径都存在且没有被气体阻挡)。
假设我们选择up
,那里有一个过滤器。你的新国家将是
{x: 0, y: 1, filters: ['S']}
现在我们知道我们可以通过燃气S
的路径,但没有其他路径。
第二个问题要复杂得多。为了做到最佳,你需要使用某种多代理寻路,但很难解决。如果你有一个很好的启发式,它可能是贪婪的最佳优先搜索。