3. 工作分配問題(回溯法)設有n件工作分配給n個人。。。

大圖書館的牧羊人發表於2020-12-19

問題描述
設有n件工作分配給n個人。將工作i分配給第j個人的費用為cij,請設計演算法,為每個人都分配1件不同的工作,並使得總費用達到最小。
實現提示:該問題的解空間是一棵排列樹,可用搜尋排列樹的回溯框架實現。
輸入樣例

3
10 2 3
2 3 4
3 4 5

輸出樣例

9

原始碼

#include<iostream>
#include<climits>
using namespace std;

int work[100];// 工作陣列,用於儲存工作編號
int work_fee[100][100];// 每個工人對應的每個工作的費用
int n, minsum= INT_MAX, newsum=0;// n表示工人個數,minsum表示最小費用和,newsum表示最新費用和

void backTrack(int k) {
	int number; // 工作編號
	if (k > n) {// 到達葉子節點
		if (newsum < minsum) { // 當最新費用小於當前最小費用時,更新最小費用
			minsum = newsum;
		}
		return;
	}

	else {// 未到達葉子節點,繼續
		for (int i = k; i <= n; i++) {
			number = work[i]; // 工作編號
			newsum = newsum + work_fee[k][number];// 將當前工人k的number號工作加入最新工作費用
			swap(work[k], work[i]);// 交換兩個位置上的工作編號
			if (newsum < minsum) { //當最新費用小於當前最小費用,繼續下一個數
				backTrack(k + 1);
			}
			swap(work[k], work[i]);// 還原之前交換的工作編號
			newsum = newsum - work_fee[k][number];// 減去之前加入的數
		}
	}
}

int main() {
	cin >> n; // 輸入工人數
	for (int i = 1; i <=n; i++) { // 初始化工作費用
		for (int j = 1; j <= n; j++) {
			cin >> work_fee[i][j];
		}
	}
	for (int i = 1; i <= n; i++) {// 初始化工作編號
		work[i] = i;
	}
	backTrack(1);// 回溯查詢
	cout << minsum << endl; // 輸出最小費用
	return 0;
}

相關文章