トップページに戻る    次のC#のサンプルへ    前のC#のサンプルへ

8-15 巡回セールスマン問題

問題

・ロンドン から パリ は 340Km
・ロンドン から マドリッド は 1270Km
・ロンドン から ローマ は 1450Km
・ロンドン から アテネ は 2400Km
・ロンドン から チューリヒ は 780Km
・パリ から マドリッド は 1060Km
・パリ から ローマ は 1120Km
・パリ から アテネ は 2100Km
・パリ から チューリヒ は 490Km
・マドリッド から ローマ は 1370Km
・マドリッド から アテネ は 2370Km
・マドリッド から チューリヒ は 1250Km
・ローマ から アテネ は 1040Km
・ローマ から チューリヒ は 700Km
・アテネ から チューリヒ は 1620Km

として順回路を求める。


ソース

using System;
using System.Linq;
using System.Collections.Generic;

class Program
{
    struct GraphDef
    {
        internal string FromPos;
        internal string ToPos;
        internal int Kyori;
    }

    struct JyoutaiDef
    {
        internal int Level;
        internal string GenzaiPos;
        internal string Path;
        internal int SumKyori;
    }

    static void Main()
    {
        var GraphArr = new GraphDef[15];
        GraphArr[0].FromPos  = "ロンドン"  ; GraphArr[0].ToPos  = "パリ"      ; GraphArr[0].Kyori  =  340;
        GraphArr[1].FromPos  = "ロンドン"  ; GraphArr[1].ToPos  = "マドリッド"; GraphArr[1].Kyori  = 1270;
        GraphArr[2].FromPos  = "ロンドン"  ; GraphArr[2].ToPos  = "ローマ"    ; GraphArr[2].Kyori  = 1450;
        GraphArr[3].FromPos  = "ロンドン"  ; GraphArr[3].ToPos  = "アテネ"    ; GraphArr[3].Kyori  = 2400;
        GraphArr[4].FromPos  = "ロンドン"  ; GraphArr[4].ToPos  = "チューリヒ"; GraphArr[4].Kyori  =  780;
        GraphArr[5].FromPos  = "パリ"      ; GraphArr[5].ToPos  = "マドリッド"; GraphArr[5].Kyori  = 1060;
        GraphArr[6].FromPos  = "パリ"      ; GraphArr[6].ToPos  = "ローマ"    ; GraphArr[6].Kyori  = 1120;
        GraphArr[7].FromPos  = "パリ"      ; GraphArr[7].ToPos  = "アテネ"    ; GraphArr[7].Kyori  = 2100;
        GraphArr[8].FromPos  = "パリ"      ; GraphArr[8].ToPos  = "チューリヒ"; GraphArr[8].Kyori  =  490;
        GraphArr[9].FromPos  = "マドリッド"; GraphArr[9].ToPos  = "ローマ"    ; GraphArr[9].Kyori  = 1370;
        GraphArr[10].FromPos = "マドリッド"; GraphArr[10].ToPos = "アテネ"    ; GraphArr[10].Kyori = 2370;
        GraphArr[11].FromPos = "マドリッド"; GraphArr[11].ToPos = "チューリヒ"; GraphArr[11].Kyori = 1250;
        GraphArr[12].FromPos = "ローマ"    ; GraphArr[12].ToPos = "アテネ"    ; GraphArr[12].Kyori = 1040;
        GraphArr[13].FromPos = "ローマ"    ; GraphArr[13].ToPos = "チューリヒ"; GraphArr[13].Kyori =  700;
        GraphArr[14].FromPos = "アテネ"    ; GraphArr[14].ToPos = "チューリヒ"; GraphArr[14].Kyori = 1620;

        var stk = new Queue<JyoutaiDef>();
        var AnswerList = new List<JyoutaiDef>();

        JyoutaiDef WillEnq;
        WillEnq.Level = 1;
        WillEnq.GenzaiPos = "ロンドン";

        for (int I = 0; I <= GraphArr.GetUpperBound(0); I++) {
            if (GraphArr[I].FromPos == "ロンドン") {
                WillEnq.GenzaiPos = GraphArr[I].ToPos;
                WillEnq.Path = "ロンドン" + "," + GraphArr[I].ToPos;
                WillEnq.SumKyori = GraphArr[I].Kyori;
                stk.Enqueue(WillEnq);
            }
        }

        int answerSumKyori = int.MaxValue;
        while (stk.Count > 0) {
            JyoutaiDef WorkJyoutai = stk.Dequeue();

            string wk = "," + WorkJyoutai.Path + ",";

            if (wk.Contains(",ロンドン,") && wk.Contains(",パリ,") &&
                wk.Contains(",マドリッド,") && wk.Contains(",ローマ,") &&
                wk.Contains(",アテネ,") && wk.Contains(",チューリヒ,")) {
                AnswerList.Add(WorkJyoutai);
                answerSumKyori = WorkJyoutai.SumKyori;
                continue;
            }

            if (WorkJyoutai.SumKyori > answerSumKyori) continue;

            WillEnq.Level = WorkJyoutai.Level + 1;

            for (int I = 0; I <= GraphArr.GetUpperBound(0); I++) {
                if (GraphArr[I].FromPos == WorkJyoutai.GenzaiPos) {
                    if (("," + WorkJyoutai.Path + ",").Contains("," + GraphArr[I].ToPos + ","))
                        continue;
                    WillEnq.GenzaiPos = GraphArr[I].ToPos;
                    WillEnq.Path = WorkJyoutai.Path + "," + GraphArr[I].ToPos;
                    WillEnq.SumKyori = WorkJyoutai.SumKyori + GraphArr[I].Kyori;
                    stk.Enqueue(WillEnq);
                }
                else if (GraphArr[I].ToPos == WorkJyoutai.GenzaiPos) {
                    if (("," + WorkJyoutai.Path + ",").Contains("," + GraphArr[I].FromPos + ","))
                        continue;
                    WillEnq.GenzaiPos = GraphArr[I].FromPos;
                    WillEnq.Path = WorkJyoutai.Path + "," + GraphArr[I].FromPos;
                    WillEnq.SumKyori = WorkJyoutai.SumKyori + GraphArr[I].Kyori;
                    stk.Enqueue(WillEnq);
                }
            }
        }

        int answerCnt = 0;
        foreach (JyoutaiDef each in AnswerList.OrderByDescending(X => X.SumKyori).ThenBy(X => X.Path)) {
            Console.WriteLine("answer{0} 距離は{1} 経路は{2}", ++answerCnt, each.SumKyori, each.Path);
        }
    }
}


実行結果

省略
answer114 距離は5090 経路はロンドン,パリ,マドリッド,ローマ,チューリヒ,アテネ
answer115 距離は4940 経路はロンドン,パリ,チューリヒ,ローマ,アテネ,マドリッド
answer116 距離は4860 経路はロンドン,パリ,チューリヒ,アテネ,ローマ,マドリッド
answer117 距離は4740 経路はロンドン,チューリヒ,パリ,マドリッド,ローマ,アテネ
answer118 距離は4560 経路はロンドン,マドリッド,パリ,チューリヒ,ローマ,アテネ
answer119 距離は4490 経路はロンドン,パリ,チューリヒ,マドリッド,ローマ,アテネ
answer120 距離は4390 経路はロンドン,パリ,マドリッド,チューリヒ,ローマ,アテネ


解説

幅優先探索で、その時点の解の中での最小距離を枝切り条件に使用してます。