最短Hamilton路徑

在這裏插入圖片描述

本題如果使用暴搜的話會超時。因爲是無向圖,所以最終我們只關心不重不漏的一條路徑的長度,而不關心內部先走哪個點後走哪個點。所以,我們需要對每個點進行位置標記,當然可以開一個visited數組記錄,但爲了操作簡便以及空間複雜度,使用二進制位表示更爲簡便。某一位爲1表示對應的該點被訪問過。因此一個二進制數就代表了一種路徑狀態。這就是狀態壓縮。狀態轉移方程爲f[i][j] = min(f[i][j], f[i-1 << j][k] + weight[k][j])。另外值得注意的是,移位運算符的優先級高於加減運算符。
#include<iostream>
#include<algorithm>
using namespace std;

const int N = 20, M = 1 << 20;
//20位從右到左表示從低到高的20個點的id
int n;
int f[M][N], weight[N][N];
int main() {
	cin >> n;

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cin >> weight[i][j];
		}
	}
	memset(f, 0x3f, sizeof f);
	f[1][0] = 0;

	for (int i = 0; i < 1 << n; i++) {
		for (int j = 0; j < n; j++) {//用j枚舉
			if (i >> j & 1) {//檢查第j位
				for (int k = 0; k < n; k++) {
					if ((i - 1 << j) >> k & 1) {//j的前驅k  因爲已經枚舉到j這個點了,所以要將它刪掉後,再檢查第k位
						f[i][j] = min(f[i][j], f[i - 1 << j][k] + weight[k][j]);//移位運算符優先級高於加減
					}
				}
			}
		}
	}
	cout << f[(1 << n) - 1][n - 1];
	return 0;
}

發佈了122 篇原創文章 · 獲贊 12 · 訪問量 9540
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章