演算法第5章上機實踐報告
阿新 • • 發佈:2018-12-18
一、實踐題目
7-2 工作分配問題 (20 分)
設有n件工作分配給n個人。將工作i分配給第j個人所需的費用為cij 。 設計一個演算法,對於給定的工作費用,為每一個人都分配1 件不同的工作,並使總費用達到最小。
輸入格式:
輸入資料的第一行有1 個正整數n (1≤n≤20)。接下來的n行,每行n個數,表示工作費用。
輸出格式:
將計算出的最小總費用輸出到螢幕。
輸入樣例:
在這裡給出一組輸入。例如:
3
10 2 3
2 3 4
3 4 5
輸出樣例:
在這裡給出相應的輸出。例如:
9
二、問題描述
找到一個 1 ~ n 的排列 s。
使得 { c[i][j] | 1 < i ≤ n, j ∈ s } 的和最小。
這樣就化簡成了排列樹問題。
三、演算法描述
1、解空間
排列樹
2、解空間樹
以 n = 3 時作為例子。
3、剪枝(約束函式或限界函式)方法描述
if(v<ans)dfs(x+1);
v 是當前工作費用,如果 v 已經大於等於求出來的最小費用,就不必再遞迴搜尋了。
4、程式碼
#include <stdio.h> #include <algorithm> using namespace std; const int maxn = 1e3+5; int n; int num[maxn], c[maxn][maxn]; int ans = 1e9, v = 0; void dfs(int x){ if(x>n){ if(v<ans){ ans = v; } return ; }for(int i = x; i <= n; ++i){ swap(num[i], num[x]); v += c[x][num[x]]; if(v<ans)dfs(x+1); v -= c[x][num[x]]; swap(num[i], num[x]); } } int main(){ scanf("%d", &n); for(int i = 1; i <= n; ++i){ num[i] = i; for(int j = 1; j <= n; ++j){ scanf("%d", &c[i][j]); } } dfs(1); printf("%d", ans); return 0; }
四、心得體會
這道題目是我跟隊友一起解決的,當時debug了很久,發現自己 v 的函式的時候寫錯了。於是改用for迴圈疊加算,老師說太慢了,就又寫了一遍現在的程式碼,就過了。。過了。。