10

Python のグラフに関する問題を解決しようとしています。それは競争力のあるプログラミングの問題であるため、他のサードパーティのパッケージは使用していません。

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

ここで2つの質問をしていると思います。

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)。問題を扱いやすくするために制約するのに役立つ 2 つの情報があります。

  1. グラフはグリッドです。
  2. ダーティ スクエアは最大で 24 個です。

ここで A* を使用するあなたの本能が気に入っています。多くの場合、移動の最小数を見つける問題を解決するのに適しています。ただし、A* にはかなりの量のコードが必要です。Branch-and-Bound アプローチ (Branch-and-Prune と呼ばれることもあります) を使用する方が良いと思います。これは、ほぼ同じくらい効率的ですが、実装がはるかに簡単です。

アイデアは、次のように、深さ優先検索を使用してすべての可能なソリューションの列挙を開始することです。

  # 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 に答える