1. 程式人生 > >演算法第5章上機實踐報告

演算法第5章上機實踐報告

一、實踐題目

 

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迴圈疊加算,老師說太慢了,就又寫了一遍現在的程式碼,就過了。。過了。。