回溯法求解TSP問題c++

回溯函數的模板爲

void backtrack(int t)
{
	if (t > n) output(x);
	else
		for (int i = t; i <= n; i++) 
		{
			swap(x[t], x[i]);
			if (constraint(t) && bound(t)) //constraint(t)爲約束函數,bound(t)爲限界函數
				backtrack(t + 1);
			swap(x[t], x[i]);
		}
}

代碼如下

#include<iostream>
using namespace std;
#define MAX 1000
int arc[100][100], x[100], bestx[100];//bestx用來記錄最優路徑或者中途產生的暫時最優路徑,x用來記錄路徑
int length = 0, best_length = MAX, n;
void Traveling(int t)
{
	int j;
	if (t > n) //到達葉子結點
	{
		if (arc[x[n]][1] != 0 && (length + arc[x[n]][1] < best_length))//推銷員到的最後一個城市與出發的城市之間有路徑,且當前總距離比當前最優值小
		{
			for (j = 1; j <= n; j++)
				bestx[j] = x[j];
			best_length = length + arc[x[n]][1];
		}
	}
	else    //沒有到達葉子結點
	{
		for (j = t; j <= n; j++)//搜索擴展結點的左右分支,即所有與當前所在城市臨近的城市
		{
			if (arc[x[t - 1]][x[j]] != 0 && (length + arc[x[t - 1]][x[j]] < best_length))//若果第t-1個城市與第t個城市之間有路徑且可以得到更短的路線
			{
				swap(x[t], x[j]);     //保存要去的第j個城市到x[t]中,從第j個城市出發繼續往下走(此時t爲父結點,j爲子結點)。因爲下一步遞歸的是t+1,遞歸函數裏又是t-1,就相當於把t傳了過去,有了swap這一步,就可以在遞歸函數裏從結點j繼續往下走了
				length += arc[x[t - 1]][x[t]]; //路線長度增加
				Traveling(t + 1);      //搜索下一個城市。不能上邊沒有swap,這裏傳參數j+1。因爲若如此做,遞歸函數裏的arc[x[t - 1]][x[j]]就會直接從j往n走,如1-3-4,而實際情況可能是1-3-2-4
				length -= arc[x[t - 1]][x[t]];//回溯到父結點,恢復length的數值,爲往另一個子結點走做準備
				swap(x[t], x[j]);//恢復x的順序(從j子結點回溯到t父結點,爲往t的另一個子結點走做準備)
			}
		}
	}
}
int main()
{
	int i, j;
	cout << "請輸入一共有幾個城市:" << endl;
	cin >> n;
	cout << "請輸入城市之間的距離(用0表示路不通)" << endl;
	for (i = 1; i <= n; i++)//從i=1開始賦值,如此i=1就代表結點1
		for (j = 1; j <= n; j++)
			cin >> arc[i][j];

	for (i = 1; i <= n; i++)
	{
		x[i] = i;
		bestx[i] = 0;
	}
	Traveling(2);//t=2表示當前正在考慮結點1與其他結點間的路徑
	cout << "城市路線:" << endl;
	for (i = 1; i <= n; i++)
		cout << bestx[i] << ' ';
	cout << bestx[1];
	cout << endl;
	cout << "最短路線長度:" << endl;
	cout << best_length << endl;
	return 0;
}

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章