回溯法解旅行推銷員問題

    [問題]某推銷員要到若干城市去推銷商品,各城市之間的路程以下圖所示。他要選定一條從駐地1出發,通過每一個城市一次,最後回到駐地的路線,並使總路程最短。數組

    

     [解析]將該問題的解空間組織以下:函數

     這棵解空間樹中從根節點B到任一葉節點的路徑均定義了圖的一條周遊路線,而圖的每一條周遊路線都剛好對應於解空間樹中從根節點B到某一葉節點的路徑。spa

     最後從根節點B開始,對解空間樹進行DFS。所選用的剪枝函數爲判斷當前已花費的路程是否小於當前已找到的最短周遊路徑的長度,屬於限界函數。搜索過程當中每到達一個葉節點,則記錄當前周遊路徑的總路程,並與已找到的最小值進行比較,根據比較結果來更新最小值。3d

     代碼以下:blog

// 推銷員當前所在的城市,初始化爲出發地1
static int currentLocation = 1;

// 存儲各城市之間距離,其中i地與j地之間的距離爲distance[i][j],n=3
static int distance[n+1][n+1];

// 標識第i站(i從0開始)爲哪一個城市,即當前路徑在解空間樹中層次爲i的節點處選擇的子連接表明的是哪一個城市,其中根節點的層次爲0,數組初始化爲{2,3,4}
static int station[n];

// 存儲當前已找到的最優周遊路線
static int optimal[n];

// 當前已找到的最短路程,初始化爲正無窮大
static int minTotalDiatance = MAX_INFINITY;

// 當前已花費的路程,初始化爲0
static int distanceGone = 0;

// 對解空間樹中層次爲i的當前節點進行DFS
void BackTrack(int i)
{
	// 檢查是否已到達葉節點
    if(i == n)
	{
		// 若是已到達葉節點,則對當前路徑所表示的周遊方案進行處理
		if(distanceGone < minTotalDiatance)
		{
			// 存儲當前已找到的最優周遊方案
			Copy(station,optimal,n);

			// 更新最短路程
			minTotalDiatance = distanceGone;
		}
	}
	else // 若是還沒有到達葉節點,則沿着當前節點的各條子連接分別進行DFS
	{
		for(int j = i;j < n;j++)
		{
			distanceGone += distance[currentLocation][station[j]];
			
			// 檢查當前節點的當前子節點是否知足限界條件,即當前已花費的路程是否小於當前已找到的最短周遊路徑的長度
			if(distanceGone < minTotalDiatance)
			{
				// 若是知足,則推動到當前節點的當前子節點
				Exchange(station,i,j);
	
				// 對新的當前節點進行DFS
				BackTrack(i + 1);

				// 對新的當前節點進行DFS完畢後,回溯到其父節點,即原來的當前節點
				Exchange(station,i,j);
				distanceGone -= distance[currentLocation][station[j]];
			}
			else
			{
				// 若是不知足,則直接回溯到當前節點
				distanceGone -= distance[currentLocation][station[j]];
			}
		}
	}
}
相關文章
相關標籤/搜索