回溯法之旅行售貨員問題


問題描述:

某售貨員要到若干城市去推銷商品,已知各城市之間的路程,他要選定一條從駐地出發,經過每個城市一遍,最后回到住地的路線,使總的路程最短。

算法描述:

回溯法,序列樹, 假設起點為 1。

算法開始時 x = [1, 2, 3, ..., n]

x[1 : n]有兩重含義 x[1 : i]代表前 i 步按順序走過的城市, x[i + 1 : n]代表還未經過的城市。利用Swap函數進行交換位置。

若當前搜索的層次i = n 時,處在排列樹的葉節點的父節點上,此時算法檢查圖G是否存在一條從頂點x[n-1] 到頂點x[n] 有一條邊,和從頂點x[n] 到頂點x[1] 也有一條邊。若這兩條邊都存在,則發現了一個旅行售貨員的回路即:新旅行路線),算法判斷這條回路的費用是否優於已經找到的當前最優回路的費用bestcost,若是,則更新當前最優值bestcost和當前最優解bestx。

若i < n 時,檢查x[i - 1]至x[i]之間是否存在一條邊, 若存在,則x [1 : i ] 構成了圖G的一條路徑,若路徑x[1: i] 的耗費小於當前最優解的耗費,則算法進入排列樹下一層,否則剪掉相應的子樹。

代碼實現:

#include <bits/stdc++.h>
using namespace std;
const int max_ = 0x3f3f3f;
const int NoEdge = -1;
int citynum;
int edgenum;
int currentcost;
int bestcost;
int Graph[100][100];
int x[100];
int bestx[100];
void InPut()
{
    int pos1, pos2, len;
    scanf("%d %d", &citynum, &edgenum);
    memset(Graph, NoEdge, sizeof(Graph));
    for(int i = 1; i <= edgenum; ++i)
    {
        scanf("%d %d %d", &pos1, &pos2, &len);
        Graph[pos1][pos2] = Graph[pos2][pos1] = len;
    }
}
void Initilize()
{
    currentcost = 0;
    bestcost = max_;
    for(int i = 1; i <= citynum; ++i)
    {
        x[i] = i;
    }
}
void Swap(int &a, int &b)
{
    int temp;
    temp = a;
    a = b;
    b = temp;
}
void BackTrack(int i) //這里的i代表第i步去的城市而不是代號為i的城市
{
    if(i == citynum)
    {
        if(Graph[x[i - 1]][x[i]] != NoEdge && Graph[x[i]][x[1]] != NoEdge && (currentcost + Graph[x[i - 1]][x[i]] + Graph[x[i]][x[1]] < bestcost || bestcost == max_))
        {
            bestcost = currentcost + Graph[x[i - 1]][x[i]] + Graph[x[i]][x[1]];
            for(int j = 1; j <= citynum; ++j)
                bestx[j] = x[j];
        }
    }
    else
    {
        for(int j =  i; j <= citynum; ++j)
        {
            if(Graph[x[i - 1]][x[j]] != NoEdge && (currentcost + Graph[x[i - 1]][x[j]] < bestcost || bestcost == max_))
            {
                Swap(x[i], x[j]);  //這里i 和 j的位置交換了, 所以下面的是currentcost += Graph[x[i - 1]][x[i]];
                currentcost += Graph[x[i - 1]][x[i]];
                BackTrack(i + 1);
                currentcost -= Graph[x[i - 1]][x[i]];
                Swap(x[i], x[j]);
            }
        }
    }
}
void OutPut()
{
    cout << "路線為:" << endl;
    for(int i = 1; i <= citynum; ++i)
        cout << bestx[i] << " ";
    cout << "1" << endl;
}
int main()
{
    InPut();
    Initilize();
    BackTrack(2);
    OutPut();
}
View Code

測試樣例:

實現結果:

 參考:王曉東《算法設計與分析》

             https://blog.csdn.net/m0_38015368/article/details/80215466


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM