1. 程式人生 > >演算法之旅行售貨員問題

演算法之旅行售貨員問題

問題描述:售貨員要到n個城市去推銷商品,已知各城市之間的路程(代價)a[][],試選擇一條路,從第一個城市出發經過每個城市一遍,最後回到出發城市所耗費的代價最小。例:

問題分析:分析可知解空間是一棵排列樹,每一條從根節點到達葉子結點的路徑代表了n個頂點的一種排列。定義x[N]記錄可行解。剪枝函式:兩個城市之間是否連通,到達當前為止的代價是否已經超過了最優代價,當前城市是否已經走過

#include <iostream>
using namespace std;
#define NoEdge -1   //兩點之間無法到達


int n=4;    //頂點(城市)數量
int cost=0; //從出發城市到當前位置的代價
int bestc=NoEdge; //最優代價
int bestx[4];     //最優解
int x[4];         //x[i]記錄第i個城市的索引
int a[4][4]=     //記錄城市之間代價,如果兩座城市之間不連通則為NoEdge
{
    -1,30,6,4,
    30,-1,5,10,
    6,5,-1,20,
    4,10,20,-1
};

bool isHave(int i,int t)
{
    for(int j=0; j<t; j++)
        if(x[j]==i)return true;
    return false;
}

void Backtrack(int t)
{
    if(t==n)
    {
        //最後一個城市和出發城市是否可到達,該條通路的代價是不是最優
        if(a[x[n-1]][0]!=NoEdge
                &&((cost+a[x[n-1]][0])<bestc||bestc==NoEdge))
        {
            for(int i=0; i<n; i++)
            {
                bestx[i]=x[i];
                bestc=cost+a[x[n-1]][0];
            }
        }
    }
    else
    {
        for(int i=0; i<n; i++)
        {
            //當前城市是否已經走過,當前城市與上一座城市之間是否連通
            if(!isHave(i,t)&&a[x[t-1]][i]!=NoEdge&&((cost+a[x[t-1]][i])<bestc||bestc==NoEdge))
            {
                cost+=a[x[t-1]][i];
                //cout<<t<<endl;
                x[t]=i;
                Backtrack(t+1);
                cost-=a[x[t-1]][i];
            }
        }
    }
}
int main()
{
    x[0]=0; //出發城市固定為第一座城市
    Backtrack(1);
    for(int i=0; i<n; i++)
        cout<<bestx[i]+1<<" ";
    cout<<endl;
    cout<<bestc<<endl;
}

時間複雜度:O(n^3)