10

我正在尝试解决与 Python 中的图形相关的问题。由于它是一个竞争性的编程问题,我没有使用任何其他 3rd 方包。

5 X 5该问题以方形网格的形式呈现图形。假设机器人位于网格上用户提供的位置。网格的索引位于(0,0)左上角和(4,4)右下角。网格中的每个单元格由以下 3 个字符中的任何一个表示。“<code>b”(ascii 值 98)表示机器人的当前位置,“<code>d”(ascii 值 100)表示网格中的脏单元格,“-”(ascii 值 45)表示网格中的干净单元格。例如,下面是机器人所在的示例网格0 0

b---d
-d--d
--dd-
--d--
----d

目标是以最少的步骤清理网格中的所有单元格。一个步骤被定义为一个任务,其中 i) 机器人改变它的位置 ii) 机器人改变细胞的状态(从 d 到 -)

假设最初标记为的位置b不需要清洁。机器人可以向上、向下、向左和向右移动。

我的方法

我已经阅读了一些关于图的教程,并决定将图建模为 25 X 25 的邻接矩阵,其中 0 表示没有路径,1 表示矩阵中的路径(因为我们只能在 4 个方向上移动)。接下来,我决定对其应用 Floyd Warshell 的所有对最短路径算法,然后对路径的值求和。但我有一种感觉,它不会起作用。我陷入困境,问题是以下之一:

i)最小生成树(我无法做到,因为我无法将网格建模和存储为图形)。

ii) A* 搜索(又是一个疯狂的猜测,但同样的问题,我无法正确地将网格建模为图形)。

如果您能提出解决此类问题的好方法,我将不胜感激。此外,关于各种形式的基于图形的问题(或指向这些问题的链接)的一些提示和伪代码也会有所帮助。谢谢

4

4 回答 4

4

我想你在这里问两个问题。

1. 如何在 Python 中将这个问题表示为图形?

当机器人四处移动时,他会从一个肮脏的广场移动到另一个,有时会沿途经过一些干净的空间。你的工作是弄清楚访问脏方块的顺序。

# Code is untested and may contain typos. :-)

# A list of the (x, y) coordinates of all of the dirty squares.
dirty_squares = [(0, 4), (1, 1), etc.]
n = len(dirty_squares)    

# Everywhere after here, refer to dirty squares by their index
# into dirty_squares.

def compute_distance(i, j):
  return (abs(dirty_squares[i][0] - dirty_squares[j][0])
          + abs(dirty_squares[i][1] - dirty_squares[j][1]))

# distances[i][j] is the cost to move from dirty square i to
# dirty square j.
distances = []
for i in range(n):
  distances.append([compute_distance(i, j) for j in range(n)])

# The x, y coordinates of where the robot starts.
start_node = (0, 0)

# first_move_distances[i] is the cost to move from the robot's
# start location to dirty square i.
first_move_distances = [
  abs(start_node[0] - dirty_squares[i][0])
      + abs(start_node[1] - dirty_squares[i][1]))
  for i in range(n)]

# order is a list of the dirty squares.
def cost(order):
  if not order:
    return 0  # Cleaning 0 dirty squares is free.
  return (first_move_distances[order[0]]
          + sum(distances[order[i]][order[i+1]]
                for i in range(len(order)-1)))

您的目标是找到一种方法来重新排序 list(range(n)) 以最小化成本。

2.我如何找到解决这个问题的最小移动数?

正如其他人指出的那样,这个问题的广义形式是难以处理的(NP-Hard)。您有两条信息有助于限制问题以使其易于处理:

  1. 该图是一个网格。
  2. 最多有 24 个脏方块。

我喜欢你在这里使用 A* 的直觉。它通常有助于解决找到最小移动数的问题。但是,A* 需要相当多的代码。我认为你最好使用分支绑定方法(有时称为分支和修剪),它应该几乎同样有效,但更容易实现。

这个想法是使用深度优先搜索开始枚举所有可能的解决方案,如下所示:

  # Each list represents a sequence of dirty nodes.
  []
  [1]
  [1, 2]
  [1, 2, 3]
  [1, 3]
  [1, 3, 2]
  [2]
  [2, 1]
  [2, 1, 3]

每次您要递归到一个分支时,检查该分支是否比目前找到的最便宜的解决方案更昂贵。如果是这样,您可以跳过整个分支。

如果这不够有效,请添加一个函数来计算剩余成本的下限。然后,如果 cost([2]) + lower_bound(set([1, 3])) 比目前找到的最便宜的解决方案更昂贵,您可以跳过整个分支。lower_bound() 越紧,您可以跳过的分支越多。

于 2013-01-13T21:00:48.237 回答
3

比方说V={v|v=b or v=d},得到一个全连通图G(V,E)。您可以计算每条边的成本,E时间复杂度为O(n^2). 之后问题就变成了完全一样:从一个指定的顶点开始,找到G覆盖的最短路径V

自 1832 年以来,我们称之为旅行商问题 (TSP) 。

于 2013-01-13T08:31:29.323 回答
1

问题当然可以存储为图表。节点(脏单元)之间的成本是它们的曼哈顿距离。忽略清洁电池的成本,因为无论采取何种方式,总成本都是相同的。

于 2013-01-13T04:29:25.997 回答
1

这个问题在我看来就像最小直线斯坦纳树问题。不幸的是,问题是 NP 很难,所以如果我是正确的,你需要提出一个近似值(基于曼哈顿距离的最小生成树)。

于 2013-01-13T09:03:51.590 回答