• 締切済み

巡回セールスマン問題を使って・・・

以前、この場で巡回セールスマン問題の考え方を使って、ということで質問に答えていただきました。その節はありがとうございました。 建築の学生なのですが、卒論の対象地の一つの分析として次のようなことを行っております。 対象地に14の交差点があって 「14の交差点全てを一筆書きで、最短経路で通過したい。」 ということをやるようになってます。 これに関して数人の方の協力でプログラムを組んでもらいました。   現在のプログラムはスタートのみ固定して、14それぞれ最短経路を探索し、ルートと最短距離を表示します。 今度はこれを、スタートとゴールともに固定して 「スタートが交差点1で、ゴールが交差点14のとき  ルートは・・。最短距離は何m。」 というふうに表示させたいのですが、プログラムに関して私はまったく素人でどのように変更すればよいかわかりません。 そこで、どのように改良すればよいか教えていただけないでしょうか。 よろしくお願いします。 文字数の関係で、プログラムをのせれないのでお答えになってくださったときにお礼の場でプログラムをお見せすることができます。

みんなの回答

  • TAGOSAKU7
  • ベストアンサー率65% (276/422)
回答No.3

結構手間がかかりそうなので、今日は全くプログラムを見てませんでした。 それじゃなくてもオリジナルの関数が多くて、コードを追いずらいです。 ぼくもやっては見ますけど、、、ムズイ、、、 とりあえず、ここの内容を見た人がやりやすいように、コメント位置をずらして、インデントしておきました。 この書き込みには基本的にはレス不要です。 nintaiさんが「ここら辺だと思う」というところがあったら補足してください。 Option Explicit Public nPoint      As Integer '交差点の数 Public dist(20, 20)   As Integer '距離を入れておくテーブル Public availRoad(20, 20) As Boolean '片道通過可能テーブル 既に通ったかどうかを記録 Public availPoint(20)  As Boolean '交差点通過可能配列 交差点を既に通ったかどうかを記録 Public checkPoint(20)  As Integer '交差点通過回数配列 Public move       As Integer '現在作りかけの経路の通過する交差点の延べ数 Public route(50)    As Integer '現在作りかけの経路 Public distance     As Integer '現在作りかけの経路の距離 Public minRoute(50)   As Integer 'これまでに見つかった最短経路 Public minMove     As Integer 'これまでに見つかった最短経路の通過する交差点の延べ数 Public minDistance   As Integer 'これまでに見つかった最短経路の距離 Public startPt     As Integer '出発交差点 '一筆経路探索(一度通過した交差点は通らない) Sub SearchMove()   Dim startStt As Integer '出発点の開始交差点番号   Dim StartEnd As Integer '出発点の終了交差点番号   'メッセージ表示   Call ShowMsg("一筆探索 実行中")   '結果削除   Call ClearResult   '道のデータを読み取る。   Call GetRoadTable      '通行可能交差点初期設定   Call ClearAvailablePoint   '検索   Call GetStartPoint(startStt, StartEnd) '出発点の範囲取得   minDistance = 30000 '大きな数値を入れておく      For startPt = startStt To StartEnd     Call ShowMsg("一筆探索 実行中 出発点" + Str(startPt))     '出発点通過するので通過不可能にする     availPoint(startPt) = False     'ルートの履歴設定     route(1) = startPt     '出発点startPtから経路検索     Call SearchMoveRepeat(startPt, 0, 1)     '通過可能に戻す     availPoint(startPt) = True   Next startPt   '結果表示   Call ShowResult      'メッセージ表示   Call ShowMsg("一筆探索 終了") End Sub '一巡経路探索(出発点へ戻る。一度通過した方向の道は通らない) Sub SearchReturn()   Dim startStt As Integer '出発点の開始交差点番号   Dim StartEnd As Integer '出発点の終了交差点番号   'メッセージ表示   Call ShowMsg("一巡探索 実行中")   '結果削除   Call ClearResult      '道のデータを読み取る。   Call GetRoadTable      '通行可能片道初期設定 & 通過交差点初期設定   ClearAvailableRoad      '検索   Call GetStartPoint(startStt, StartEnd) '出発点の範囲取得   '大きな数値を入れておく   minDistance = 30000   For startPt = startStt To StartEnd     Call ShowMsg("一巡探索 実行中 出発点" + Str(startPt))     'ルートの履歴設定     route(1) = startPt     '出発点1回通過済み     checkPoint(startPt) = 1     '出発点startPtから経路検索     Call SearchReturnRepeat(startPt, 0, 1)     '出発点を未通過に戻す     checkPoint(startPt) = 0   Next startPt   '結果表示   Call ShowResult      'メッセージ表示   Call ShowMsg("一巡探索 終了") End Sub '一筆経路探索(一度通過した交差点は通らない) '現在交差点curPtに居て、作りかけの経路の距離はdistance、既に交差点move個を通過した。 Private Sub SearchMoveRepeat(curPt As Integer, distance As Integer, move As Integer)   Dim branch As Integer '分岐   Dim nextPt As Integer '次交差点   Dim k    As Integer   For branch = 1 To nPoint - 1     '次交差点番号     nextPt = (curPt + branch - 1) Mod nPoint + 1     '次交差点通過可能の場合     If availPoint(nextPt) Then       '現在の最短距離を越えたら、その先を調べる必要なし。       If minDistance > distance + dist(curPt, nextPt) Then         '次交差点を通過するので通過不可能にする         availPoint(nextPt) = False         'ルートの履歴設定         route(move + 1) = nextPt         'まだ全交差点を回っていない         If move + 1 < nPoint Then           '経路を延ばす。           Call SearchMoveRepeat(nextPt, distance + dist(curPt, nextPt), move + 1)         '全交差点を回っている場合最短記録更新。         Else           '全距離           minDistance = distance + dist(curPt, nextPt)           '全交差点数           minMove = move + 1           '全ルート履歴           For k = 1 To minMove             minRoute(k) = route(k)           Next k           '結果表示           Call ShowResult         End If         '前の交差点に戻るので,通過可能に戻す         availPoint(nextPt) = True       End If     End If   Next branch End Sub '一巡経路探索(出発点へ戻る。一度通過した方向の道は通らない) '現在交差点curPtに居て、作りかけの経路の距離はdistance、既に交差点move個を通過した。 Private Sub SearchReturnRepeat(curPt As Integer, distance As Integer, move As Integer)   Dim branch As Integer '分岐   Dim nextPt As Integer '次交差点   Dim k    As Integer   For branch = 1 To nPoint - 1     '次交差点番号     nextPt = (curPt + branch - 1) Mod nPoint + 1          '次交差点片道が通過可能の場合     If availRoad(curPt, nextPt) Then       '現在の最短距離を越えたら、その先を調べる必要なし。       If minDistance > distance + dist(curPt, nextPt) Then         '次交差点への片道を通過するので通過不可能にする         availRoad(curPt, nextPt) = False         '次交差点の通行回数を増加する         checkPoint(nextPt) = checkPoint(nextPt) + 1         'ルートの履歴設定         route(move + 1) = nextPt         'まだ全交差点を回っていない         If Not CheckAllPoint(move) Then           '次交差点が出発点でない(全交差点未周回で出発点にもどると打ち切り)           If nextPt <> startPt Then             '経路を延ばす。             Call SearchReturnRepeat(nextPt, distance + dist(curPt, nextPt), move + 1)           End If         '全交差点を回っている場合,出発点を加える         Else           '現在の最短距離を越えたら、その先を調べる必要なし。           If minDistance > distance + dist(curPt, nextPt) + dist(nextPt, startPt) Then             '最短記録更新。             route(move + 2) = startPt 'ルートの最後に出発点設定             minDistance = distance + dist(curPt, nextPt) + dist(nextPt, startPt)             minMove = move + 2             For k = 1 To minMove               minRoute(k) = route(k)             Next k             '結果表示             Call ShowResult           End If         End If         '前の交差点に戻るので,通過可能に戻す         availRoad(curPt, nextPt) = True         '前の交差点に戻るので,通過回数を戻す         checkPoint(nextPt) = checkPoint(nextPt) - 1       End If     End If   Next branch End Sub '全交差点を通過したかどうか。 Private Function CheckAllPoint(move As Integer)   Dim i As Integer   Dim pass As Integer '通過交差点数   CheckAllPoint = False    '交差点の通過数が全交差点数以下なら絶対無理   If move + 1 < nPoint Then Exit Function   pass = 0   For i = 1 To nPoint     '通過済み交差点のカウント     If checkPoint(i) > 0 Then pass = pass + 1   Next i      '通過済み交差点数が全交差点数と等しい   CheckAllPoint = (pass = nPoint) End Function '道のデータを読み取る。 Private Sub GetStartPoint(startStt As Integer, StartEnd As Integer)   Dim stt As Integer '指定出発点番号      stt = Range("start")   If stt = 0 Then     startStt = 1     StartEnd = nPoint   Else     startStt = stt     StartEnd = stt   End If End Sub '道のデータを読み取る。 Private Sub GetRoadTable()   Dim i As Integer   Dim j As Integer      nPoint = Range("points").Value   With Range("road")     For i = 1 To nPoint       For j = 1 To nPoint       dist(i, j) = .Cells(i, j).Value       Next j     Next i   End With End Sub '通行可能交差点初期設定 Private Sub ClearAvailablePoint()   Dim i As Integer      For i = 1 To nPoint     availPoint(i) = True   Next i End Sub '通行可能片道初期設定 & 通過交差点初期設定 Private Sub ClearAvailableRoad()   Dim i As Integer   Dim j As Integer   For i = 1 To nPoint     checkPoint(i) = False '最初は全交差点未通過     For j = 1 To nPoint       availRoad(i, j) = dist(i, j) > 0 '片道に距離が設定されていたらTrue     Next j   Next i End Sub '結果を削除 Private Sub ClearResult()   Dim k As Integer   Range("minDistance").Clear   With Range("route")     For k = 1 To 20       .Cells(k, 1).Clear     Next k   End With End Sub '結果を表示 Private Sub ShowResult()   Dim k As Integer   Range("minDistance").Value = minDistance   With Range("route")     For k = 1 To minMove       .Cells(k, 1).Value = minRoute(k)     Next k   .Range(Cells(minMove + 1, 1), Cells(minMove * 2, 1)).Value = ""   End With End Sub 'メッセージを表示 Private Sub ShowMsg(msg As String)   Range("message").Value = msg End Sub

全文を見る
すると、全ての回答が全文表示されます。
  • ykkw_2001
  • ベストアンサー率26% (267/1014)
回答No.2

>プログラムを組んでもらいました。 ということは、 スタートが交差点xで、ゴールが交差点1のとき から >スタートが交差点xで、ゴールが交差点14のとき まで、出てくるのがあるっていう風に読み取れるのですが、違いますか? もしそうなら、スタート、ゴールを入力させて、合致する答えのみ表示させればいいのではないですか? 素人の人が、計算の部分を触らずに、入出力だけ細工して済むなら、最良の解決法です。(企業においては・・)

nintai
質問者

お礼

ご回答、ありがとうございます。 組んでもらったプログラムは、入力する部分はスタートのみだったものです。 以下が、組んでもらったプログラムです。 このうち、一筆経路探索の方です。 Option Explicit Public nPoint As Integer '交差点の数 Public dist(20, 20) As Integer '距離を入れておくテーブル Public availRoad(20, 20) As Boolean '片道通過可能テーブル 既に通ったかどうかを記録 Public availPoint(20) As Boolean '交差点通過可能配列 交差点を既に通ったかどうかを記録 Public checkPoint(20) As Integer '交差点通過回数配列 Public move As Integer '現在作りかけの経路の通過する交差点の延べ数 Public route(50) As Integer '現在作りかけの経路 Public distance As Integer '現在作りかけの経路の距離 Public minRoute(50) As Integer 'これまでに見つかった最短経路 Public minMove As Integer 'これまでに見つかった最短経路の通過する交差点の延べ数 Public minDistance As Integer 'これまでに見つかった最短経路の距離 Public startPt As Integer '出発交差点 '一筆経路探索(一度通過した交差点は通らない) Sub SearchMove() Dim startStt As Integer '出発点の開始交差点番号 Dim StartEnd As Integer '出発点の終了交差点番号 ShowMsg "一筆探索 実行中" 'メッセージ表示 ClearResult '結果削除 GetRoadTable '道のデータを読み取る。 ClearAvailablePoint '通行可能交差点初期設定 '検索 GetStartPoint startStt, StartEnd '出発点の範囲取得 minDistance = 30000 '大きな数値を入れておく For startPt = startStt To StartEnd ShowMsg "一筆探索 実行中 出発点" + str(startPt) availPoint(startPt) = False '出発点通過するので通過不可能にする route(1) = startPt 'ルートの履歴設定 SearchMoveRepeat startPt, 0, 1 '出発点startPtから経路検索 availPoint(startPt) = True '通過可能に戻す Next '結果表示 ShowResult 'メッセージ表示 ShowMsg "一筆探索 終了" End Sub '一巡経路探索(出発点へ戻る。一度通過した方向の道は通らない) Sub SearchReturn() Dim startStt As Integer '出発点の開始交差点番号 Dim StartEnd As Integer '出発点の終了交差点番号 ShowMsg "一巡探索 実行中" 'メッセージ表示 ClearResult '結果削除 GetRoadTable '道のデータを読み取る。 ClearAvailableRoad '通行可能片道初期設定 & 通過交差点初期設定 '検索 GetStartPoint startStt, StartEnd '出発点の範囲取得 minDistance = 30000 '大きな数値を入れておく For startPt = startStt To StartEnd ShowMsg "一巡探索 実行中 出発点" + str(startPt) route(1) = startPt 'ルートの履歴設定 checkPoint(startPt) = 1 '出発点1回通過済み SearchReturnRepeat startPt, 0, 1 '出発点startPtから経路検索 checkPoint(startPt) = 0 '出発点を未通過に戻す Next '結果表示 ShowResult 'メッセージ表示 ShowMsg "一巡探索 終了" End Sub '一筆経路探索(一度通過した交差点は通らない) '現在交差点curPtに居て、作りかけの経路の距離はdistance、既に交差点move個を通過した。 Private Sub SearchMoveRepeat(curPt As Integer, distance As Integer, move As Integer) Dim branch As Integer '分岐 Dim nextPt As Integer '次交差点 Dim k As Integer For branch = 1 To nPoint - 1 nextPt = (curPt + branch - 1) Mod nPoint + 1 '次交差点番号 If availPoint(nextPt) Then '次交差点通過可能の場合 If minDistance > distance + dist(curPt, nextPt) Then '現在の最短距離を越えたら、その先を調べる必要なし。 availPoint(nextPt) = False '次交差点を通過するので通過不可能にする route(move + 1) = nextPt 'ルートの履歴設定 If move + 1 < nPoint Then 'まだ全交差点を回っていない SearchMoveRepeat nextPt, distance + dist(curPt, nextPt), move + 1 '経路を延ばす。 Else '全交差点を回っている場合最短記録更新。 minDistance = distance + dist(curPt, nextPt) '全距離 minMove = move + 1 '全交差点数 For k = 1 To minMove '全ルート履歴 minRoute(k) = route(k) Next ShowResult '結果表示 End If availPoint(nextPt) = True '前の交差点に戻るので,通過可能に戻す End If End If Next End Sub '一巡経路探索(出発点へ戻る。一度通過した方向の道は通らない) '現在交差点curPtに居て、作りかけの経路の距離はdistance、既に交差点move個を通過した。 Private Sub SearchReturnRepeat(curPt As Integer, distance As Integer, move As Integer) Dim branch As Integer '分岐 Dim nextPt As Integer '次交差点 Dim k As Integer For branch = 1 To nPoint - 1 nextPt = (curPt + branch - 1) Mod nPoint + 1 '次交差点番号 If availRoad(curPt, nextPt) Then '次交差点片道が通過可能の場合 If minDistance > distance + dist(curPt, nextPt) Then '現在の最短距離を越えたら、その先を調べる必要なし。 availRoad(curPt, nextPt) = False '次交差点への片道を通過するので通過不可能にする checkPoint(nextPt) = checkPoint(nextPt) + 1 '次交差点の通行回数を増加する route(move + 1) = nextPt 'ルートの履歴設定 If Not CheckAllPoint(move) Then 'まだ全交差点を回っていない If nextPt <> startPt Then '次交差点が出発点でない(全交差点未周回で出発点にもどると打ち切り) SearchReturnRepeat nextPt, distance + dist(curPt, nextPt), move + 1 '経路を延ばす。 End If Else '全交差点を回っている場合,出発点を加える If minDistance > distance + dist(curPt, nextPt) + dist(nextPt, startPt) Then '現在の最短距離を越えたら、その先を調べる必要なし。 '最短記録更新。 route(move + 2) = startPt 'ルートの最後に出発点設定 minDistance = distance + dist(curPt, nextPt) + dist(nextPt, startPt) minMove = move + 2 For k = 1 To minMove minRoute(k) = route(k) Next ShowResult '結果表示 End If End If availRoad(curPt, nextPt) = True '前の交差点に戻るので,通過可能に戻す checkPoint(nextPt) = checkPoint(nextPt) - 1 '前の交差点に戻るので,通過回数を戻す End If End If Next End Sub '全交差点を通過したかどうか。 Private Function CheckAllPoint(move As Integer) Dim i As Integer Dim pass As Integer '通過交差点数 CheckAllPoint = False If move + 1 < nPoint Then Exit Function '交差点の通過数が全交差点数以下なら絶対無理 pass = 0 For i = 1 To nPoint If checkPoint(i) > 0 Then pass = pass + 1 '通過済み交差点のカウント Next CheckAllPoint = (pass = nPoint) '通過済み交差点数が全交差点数と等しい End Function '道のデータを読み取る。 Private Sub GetStartPoint(startStt As Integer, StartEnd As Integer) Dim stt As Integer '指定出発点番号 stt = Range("start") If stt = 0 Then startStt = 1 StartEnd = nPoint Else startStt = stt StartEnd = stt End If End Sub '道のデータを読み取る。 Private Sub GetRoadTable() Dim i As Integer Dim j As Integer nPoint = Range("points").Value With Range("road") For i = 1 To nPoint For j = 1 To nPoint dist(i, j) = .Cells(i, j).Value Next Next End With End Sub '通行可能交差点初期設定 Private Sub ClearAvailablePoint() Dim i As Integer For i = 1 To nPoint availPoint(i) = True Next End Sub '通行可能片道初期設定 & 通過交差点初期設定 Private Sub ClearAvailableRoad() Dim i As Integer Dim j As Integer For i = 1 To nPoint checkPoint(i) = False '最初は全交差点未通過 For j = 1 To nPoint availRoad(i, j) = dist(i, j) > 0 '片道に距離が設定されていたらTrue Next Next End Sub '結果を削除 Private Sub ClearResult() Dim k As Integer Range("minDistance").Clear With Range("route") For k = 1 To 20 .Cells(k, 1).Clear Next k End With End Sub '結果を表示 Private Sub ShowResult() Dim k As Integer Range("minDistance").Value = minDistance With Range("route") For k = 1 To minMove .Cells(k, 1).Value = minRoute(k) Next k .Range(Cells(minMove + 1, 1), Cells(minMove * 2, 1)).Value = "" End With End Sub 'メッセージを表示 Private Sub ShowMsg(msg As String) Range("message").Value = msg End Sub

全文を見る
すると、全ての回答が全文表示されます。
  • TAGOSAKU7
  • ベストアンサー率65% (276/422)
回答No.1

見てみたいですー

nintai
質問者

お礼

ありがとうございます。 見ていただけますか? 以下が組んでもらったプログラムで「一筆経路探索」の方です。 Option Explicit Public nPoint As Integer '交差点の数 Public dist(20, 20) As Integer '距離を入れておくテーブル Public availRoad(20, 20) As Boolean '片道通過可能テーブル 既に通ったかどうかを記録 Public availPoint(20) As Boolean '交差点通過可能配列 交差点を既に通ったかどうかを記録 Public checkPoint(20) As Integer '交差点通過回数配列 Public move As Integer '現在作りかけの経路の通過する交差点の延べ数 Public route(50) As Integer '現在作りかけの経路 Public distance As Integer '現在作りかけの経路の距離 Public minRoute(50) As Integer 'これまでに見つかった最短経路 Public minMove As Integer 'これまでに見つかった最短経路の通過する交差点の延べ数 Public minDistance As Integer 'これまでに見つかった最短経路の距離 Public startPt As Integer '出発交差点 '一筆経路探索(一度通過した交差点は通らない) Sub SearchMove() Dim startStt As Integer '出発点の開始交差点番号 Dim StartEnd As Integer '出発点の終了交差点番号 ShowMsg "一筆探索 実行中" 'メッセージ表示 ClearResult '結果削除 GetRoadTable '道のデータを読み取る。 ClearAvailablePoint '通行可能交差点初期設定 '検索 GetStartPoint startStt, StartEnd '出発点の範囲取得 minDistance = 30000 '大きな数値を入れておく For startPt = startStt To StartEnd ShowMsg "一筆探索 実行中 出発点" + str(startPt) availPoint(startPt) = False '出発点通過するので通過不可能にする route(1) = startPt 'ルートの履歴設定 SearchMoveRepeat startPt, 0, 1 '出発点startPtから経路検索 availPoint(startPt) = True '通過可能に戻す Next '結果表示 ShowResult 'メッセージ表示 ShowMsg "一筆探索 終了" End Sub '一巡経路探索(出発点へ戻る。一度通過した方向の道は通らない) Sub SearchReturn() Dim startStt As Integer '出発点の開始交差点番号 Dim StartEnd As Integer '出発点の終了交差点番号 ShowMsg "一巡探索 実行中" 'メッセージ表示 ClearResult '結果削除 GetRoadTable '道のデータを読み取る。 ClearAvailableRoad '通行可能片道初期設定 & 通過交差点初期設定 '検索 GetStartPoint startStt, StartEnd '出発点の範囲取得 minDistance = 30000 '大きな数値を入れておく For startPt = startStt To StartEnd ShowMsg "一巡探索 実行中 出発点" + str(startPt) route(1) = startPt 'ルートの履歴設定 checkPoint(startPt) = 1 '出発点1回通過済み SearchReturnRepeat startPt, 0, 1 '出発点startPtから経路検索 checkPoint(startPt) = 0 '出発点を未通過に戻す Next '結果表示 ShowResult 'メッセージ表示 ShowMsg "一巡探索 終了" End Sub '一筆経路探索(一度通過した交差点は通らない) '現在交差点curPtに居て、作りかけの経路の距離はdistance、既に交差点move個を通過した。 Private Sub SearchMoveRepeat(curPt As Integer, distance As Integer, move As Integer) Dim branch As Integer '分岐 Dim nextPt As Integer '次交差点 Dim k As Integer For branch = 1 To nPoint - 1 nextPt = (curPt + branch - 1) Mod nPoint + 1 '次交差点番号 If availPoint(nextPt) Then '次交差点通過可能の場合 If minDistance > distance + dist(curPt, nextPt) Then '現在の最短距離を越えたら、その先を調べる必要なし。 availPoint(nextPt) = False '次交差点を通過するので通過不可能にする route(move + 1) = nextPt 'ルートの履歴設定 If move + 1 < nPoint Then 'まだ全交差点を回っていない SearchMoveRepeat nextPt, distance + dist(curPt, nextPt), move + 1 '経路を延ばす。 Else '全交差点を回っている場合最短記録更新。 minDistance = distance + dist(curPt, nextPt) '全距離 minMove = move + 1 '全交差点数 For k = 1 To minMove '全ルート履歴 minRoute(k) = route(k) Next ShowResult '結果表示 End If availPoint(nextPt) = True '前の交差点に戻るので,通過可能に戻す End If End If Next End Sub '一巡経路探索(出発点へ戻る。一度通過した方向の道は通らない) '現在交差点curPtに居て、作りかけの経路の距離はdistance、既に交差点move個を通過した。 Private Sub SearchReturnRepeat(curPt As Integer, distance As Integer, move As Integer) Dim branch As Integer '分岐 Dim nextPt As Integer '次交差点 Dim k As Integer For branch = 1 To nPoint - 1 nextPt = (curPt + branch - 1) Mod nPoint + 1 '次交差点番号 If availRoad(curPt, nextPt) Then '次交差点片道が通過可能の場合 If minDistance > distance + dist(curPt, nextPt) Then '現在の最短距離を越えたら、その先を調べる必要なし。 availRoad(curPt, nextPt) = False '次交差点への片道を通過するので通過不可能にする checkPoint(nextPt) = checkPoint(nextPt) + 1 '次交差点の通行回数を増加する route(move + 1) = nextPt 'ルートの履歴設定 If Not CheckAllPoint(move) Then 'まだ全交差点を回っていない If nextPt <> startPt Then '次交差点が出発点でない(全交差点未周回で出発点にもどると打ち切り) SearchReturnRepeat nextPt, distance + dist(curPt, nextPt), move + 1 '経路を延ばす。 End If Else '全交差点を回っている場合,出発点を加える If minDistance > distance + dist(curPt, nextPt) + dist(nextPt, startPt) Then '現在の最短距離を越えたら、その先を調べる必要なし。 '最短記録更新。 route(move + 2) = startPt 'ルートの最後に出発点設定 minDistance = distance + dist(curPt, nextPt) + dist(nextPt, startPt) minMove = move + 2 For k = 1 To minMove minRoute(k) = route(k) Next ShowResult '結果表示 End If End If availRoad(curPt, nextPt) = True '前の交差点に戻るので,通過可能に戻す checkPoint(nextPt) = checkPoint(nextPt) - 1 '前の交差点に戻るので,通過回数を戻す End If End If Next End Sub '全交差点を通過したかどうか。 Private Function CheckAllPoint(move As Integer) Dim i As Integer Dim pass As Integer '通過交差点数 CheckAllPoint = False If move + 1 < nPoint Then Exit Function '交差点の通過数が全交差点数以下なら絶対無理 pass = 0 For i = 1 To nPoint If checkPoint(i) > 0 Then pass = pass + 1 '通過済み交差点のカウント Next CheckAllPoint = (pass = nPoint) '通過済み交差点数が全交差点数と等しい End Function '道のデータを読み取る。 Private Sub GetStartPoint(startStt As Integer, StartEnd As Integer) Dim stt As Integer '指定出発点番号 stt = Range("start") If stt = 0 Then startStt = 1 StartEnd = nPoint Else startStt = stt StartEnd = stt End If End Sub '道のデータを読み取る。 Private Sub GetRoadTable() Dim i As Integer Dim j As Integer nPoint = Range("points").Value With Range("road") For i = 1 To nPoint For j = 1 To nPoint dist(i, j) = .Cells(i, j).Value Next Next End With End Sub '通行可能交差点初期設定 Private Sub ClearAvailablePoint() Dim i As Integer For i = 1 To nPoint availPoint(i) = True Next End Sub '通行可能片道初期設定 & 通過交差点初期設定 Private Sub ClearAvailableRoad() Dim i As Integer Dim j As Integer For i = 1 To nPoint checkPoint(i) = False '最初は全交差点未通過 For j = 1 To nPoint availRoad(i, j) = dist(i, j) > 0 '片道に距離が設定されていたらTrue Next Next End Sub '結果を削除 Private Sub ClearResult() Dim k As Integer Range("minDistance").Clear With Range("route") For k = 1 To 20 .Cells(k, 1).Clear Next k End With End Sub '結果を表示 Private Sub ShowResult() Dim k As Integer Range("minDistance").Value = minDistance With Range("route") For k = 1 To minMove .Cells(k, 1).Value = minRoute(k) Next k .Range(Cells(minMove + 1, 1), Cells(minMove * 2, 1)).Value = "" End With End Sub 'メッセージを表示 Private Sub ShowMsg(msg As String) Range("message").Value = msg End Sub

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 巡回セールスマン問題の考え方を使って・・・。

    以前、この場で巡回セールスマン問題の考え方を使って、ということで質問に答えていただきました。その節はありがとうございました。 建築の学生なのですが、卒論の対象地の一つの分析として次のようなことを行っております。 対象地に14の交差点があって 「14の交差点全てを一筆書きで、最短経路で通過したい。」 ということをやるようになってます。 これに関して数人の方の協力でプログラムを組んでもらいました。   現在のプログラムはスタートのみ固定して、14それぞれ最短経路を探索し、ルートと最短距離を表示します。 今度はこれを、スタートとゴールともに固定して 「スタートが交差点1で、ゴールが交差点14のとき  ルートは・・。最短距離は何m。」 というふうに表示させたいのですが、プログラムに関して私はまったく素人でどのように変更すればよいかわかりません。 そこで、どのように改良すればよいか教えていただけないでしょうか。 よろしくお願いします。

  • 巡回セールスマン問題を使って・・・

    すいません。数学に関してまったくの素人です。 建築の学生なのですが、卒論の対象地の一つの分析として次のようなことを行っております。 「対象地に12の交差点があって 1.この交差点全てを最短経路でまわりたい。(スタートとゴールがいっしょ。) 2.交差点全てを最短経路で通過したい。(スタートとゴールはちがう) ということをやるようになってます。 1.に関しては巡回セールスマン問題の分岐限定法でパズル的にとけばいいのでしょうか? 2.に関してはまったくわかりません。そもそもどのようにスタートとゴールを設定すればいいのか・・・ また上記のような場合に適応できるプログラムは出回っているのでしょうか?もしくは自分で作れるものなのでしょうか?プログラムに関してもまったく素人です。 このように質問ばかりですいません。書いてあることでわからないことがあれば、言ってください。わかるかたご教授ください。お願いします。

  • 巡回セールスマン問題の類似問題

    卒業研究の題材で巡回セールスマン問題をあつかっていて、解法に困ってます。巡回セールスマン問題の定義は「完全グラフにおいて全ての都市を回り、始点にもどってくる最短経路を探す問題」だと思うのですが、私の研究室の教授が、完全グラフ(すべての都市に道が繋がっているグラフ)ではなく、道の決まってるグラフで、しかも始点に戻ってくる必要のないグラフで考えるようにいわれました。確かに現実問題として全ての家に道が繋がっているケースは考えられません。たとえば、世界の全ての空港を最短距離で巡ろうとしたとき、今いる国からいけるところといけないところがあるのと同じです。 ただ、この場合の解法として、巡回しなくてもよいといっても完全グラフではないのでひたすら最短の道を選んでいては解がえられず、ハミルトン経路のように同じ道を2度使ってはいけないという定義でもないので、これもつかえません。この問題はいったいどう定義したらいいものでしょうか?また、このような問題には、すでに解法があるのでしょうか?難しい問題だと思いますが、少しでも解る方、おねがいいたします。

  • 巡回セールスマン問題

    このプログラミングを実際に視覚的(探索している状況など)に表したいんですが、どのようにすべきなのでしょうか? いろいろ参考書を見たのですが、わかりませんでした。 import java.io.*; public class TSP { public static void main(String[] args) { TSP instance = new TSP(); TspPoint[] points = new TspPoint[5]; //コンポーネントの作成 points[0] = new TspPoint("A", 5, 10); points[1] = new TspPoint("B", 4, 2); points[2] = new TspPoint("C", 6, 3); points[3] = new TspPoint("D", 3, 4); points[4] = new TspPoint("E", 2, 7); instance.setPoints(points); instance.traveling(); instance.dispResult(); } private TspPoint[] points; private double min_distance; private int[] min_route; public void setPoints(TspPoint[] points) { this.points = points; } public void traveling() { min_distance = Double.MAX_VALUE; min_route = new int[points.length]; int p1, p2, p3, p4, p5; p1 = 0; for (p2 = 1; p2 < 5; p2++) { for (p3 = 1; p3 < 5; p3++) { for (p4 = 1; p4 < 5; p4++) { for (p5 = 1; p5 < 5; p5++) { if (p1 == p2 || p1 == p3 || p1 == p4 || p1 == p5 || p2 == p3 || p2 == p4 || p2 == p5 || p3 == p4 || p3 == p5 || p4 == p5) { // 重複する地点は対象外 } else { // p1→p2→p3→p4→p5→p1への巡回経路長を求める double distance = 0.0; distance += calcDistance(points[p1], points[p2]); distance += calcDistance(points[p2], points[p3]); distance += calcDistance(points[p3], points[p4]); distance += calcDistance(points[p4], points[p5]); distance += calcDistance(points[p5], points[p1]); if (distance < min_distance) { // 現在のところの最短経路を覚えておく min_route[0] = p1; min_route[1] = p2; min_route[2] = p3; min_route[3] = p4; min_route[4] = p5; // 最短距離を記憶する min_distance = distance; } } } } } } } public void dispResult() { System.out.print("最小の巡回経路は "); for (int i = 0; i < 5; i++) { System.out.print(points[min_route[i]].toString() + " → "); } System.out.println(points[min_route[0]].toString()); System.out.println("巡回経路長は " + min_distance); } public double calcDistance(TspPoint a, TspPoint b) { double temp; temp = (a.getX() - b.getX()) * (a.getX() - b.getX()) + (a.getY() - b.getY()) * (a.getY() - b.getY()); return Math.sqrt(temp); //平方根を返す } } class TspPoint { private String name; private int x; private int y; public TspPoint(String name, int x, int y) { this.name = name; this.x = x; this.y = y; } public String getName() { return name; } public int getX() { return x; } public int getY() { return y; } public String toString() { return name + "(" + x + "," + y + ")"; } }

  • 最短距離を求める問題(ダイクストラ法)の原理

    グラフ(経路)の情報があり、それを用いて最短距離を探索するアルゴリズムにダイクストラ法というものがあります。 このアルゴリズムでは常に正しい解を導けるということなのでしょうか。調べてみると負の距離があったらダメというのがありましたが、これは除外しての話ですが。 また、このアルゴリズムがなぜ正しいだろうと思えるのかについて理解できればなんとなくわかるような気がします。そこで、wikipediaを読んでみたのですが、さっぱり分かりませんでした。ちょっと引用します。 ”最短経路問題は、ビー玉と紐を用いて解くことが出来る。 まずビー玉を頂点、紐を辺にするグラフを工作する。 グラフを板の上に置き、スタートの頂点にあたるビー玉だけをつまむ。 グラフが置かれている板を取り除くと、グラフは自由落下を始めるが、 スタートにあたるビー玉を持っているので、スタート地点から近いビー玉から順に落下が止まる。 ゴールにあたるビー玉が止まったとき、ゴールにあたるビー玉はスタートにあたるビー玉まで紐で一直線で結ばれている。 この直線が最短経路である。” ビー玉が経路の構成点で紐が経路なのかなということはわかりますが、それを板の上にのせて板がを取り除く、あたりから何が何だかさっぱりわかりません。板は水平に置かれているなら板が消えたら全部落下するだけのように思えますし。でもこれが理解できるとアルゴリズムの思想が理解でき、その妥当性とか限界について予想がつくのだろうと思います。 他に何かイメージがつかみやすい説明があるでしょうか。 また、ダイクストラ法は情報処理としては初等的なものなのでしょうか。それとも結構アドバンスドなものなのでしょうか。 サンプルプログラムを調べてみたらC・C++が多いようなのでこちらにお尋ねしてみました。 よろしくお願いします。

  • 経路探索

    よろしくお願いします。 現在経路探索問題のプログラムを書いています。 そこでわからない点があったので教えてください。 以下のような(n行,m列)の経路があります。 (0,0)-(0,1)-(0,2)-(0,3) (1,0)-(1,1)-(1,2)-(1,3) (2,0)-(2,1)-(2,2)-(2,3) (3,0)-(3,1)-(3,2)-(3,3) (4,0)-(4,1)-(4,2)-(4,3) スタートを(4,3)としてゴール(0,0)にたどり着く全ての経路を求めたいです。 条件としてある点から 左(例えば(4,3)⇒(4,2)) 上(例えば(4,3)⇒(3,3)) 斜め(例えば(4,3)⇒(3,2)) にしか進むことはできません。 このような仕様のアルゴリズムはどのように書けばよいのでしょうか?? ご解答要路しくお願いします。

  • 最短経路を計算するプログラム

    下の図のようなものを用いて、スタート(S)からゴール(G)までいく最短経路を計算するプログラムをVisual Studio 2005のC++で作ったアルゴリズムが知りたいです。

  • プログラム仕様について

    ダイクストラを用いて最短経路探索のプログラムをJAVAで作ろうとしているのですが、肝心なプログラム仕様書及びフローチャートが書けません。 どなたかお力おかしください

  • 最長経路探索

    グラフの最長経路(クリティカルパス)を求めたいのですが、 ・閉路無し有向グラフ ・重み付きグラフ(辺ではなくノードの方に重みがある) ・スタートとゴールのノードが各々1つ与えられている ・スタートからどの経路を辿ってもゴールには辿り着く 以上のような条件の時に、どのようなアルゴリズムを用いれば良いのでしょうか? 幅優先探索で求められそうな気がしたのですが、どうも上手くいきません。 言語はVBAで、そもそも詳しくないのですが、 考え方など教えて頂けないでしょうか。 お願い致します。

  • 最短距離の問題です

    最短距離の問題です 座標空間において,x, y, z 座標の少なくとも1つが整数であるような点の集合 A を考える. (0,0,0) から (3,3,3) まで,A に属する点だけを通って移動する 最短経路の長さを求めよ. 答えは√41 です

Microsoftライセンス認証の問題
このQ&Aのポイント
  • NECのPC-GN21DJSA9でPremiumOfficeが内蔵されているパソコンで、MicrosoftOfficeのプロダクトキーを紛失してしまってライセンス認証ができない状態です。
  • ライセンス認証ができなければ、今月25日からOfficeが使えなくなります。
  • ネット対応のみでAIが対応しているため、Microsoftにプロダクトキーの再発行か再購入の問い合わせをすることができません。どうしたらきちんと問い合わせできるでしょうか?
回答を見る

専門家に質問してみよう