算法第五章实践报告

 

1、实践题目 :工作分配问题

 

2、问题描述

设有n件工作分配给n个人。将工作i分配给第j个人所需的费用为cij 。 设计一个算法,对于给定的工作费用,为每一个人都分配1 件不同的工作,并使总费用达到最小。

输入:输入数据的第一行有1 个正整数n (1≤n≤20)。接下来的n行,每行n个数,表示工作费用。

输出:将计算出的最小总费用输出到屏幕。

 

3、算法描述(包括解空间,画出测试样例的解空间树,剪枝(约束函数或限界函数)方法描述)

 1 #include<iostream>
 2 using namespace std;
 3 
 4 int minExp =0 ;  //初始化当前费用和最小费用为0
 5 int n ;  //n个人n件工作 
 6 int a[50][50] ;
 7 int x[50] ;
 8 
 9 
10 void backtrace(int i , int cexp){    //第i个工作 
11     
12     
13     if(i > n ){         
14         if(cexp < minExp)  minExp = cexp;
15         return ;
16     }
17     if(cexp < minExp){
18       for(int j = 1 ; j <= n ; j++){
19           if(x[j] == 0){    //第j个人是否有工作
20               x[j] = 1 ;
21               backtrace(i+1 , cexp + a[i][j]) ;
22               x[j] = 0 ;
23     }
24 }
25 }
26 }
27 int main()
28 {    
29     cin >> n ;
30     
31     for(int i=1 ; i<=n ; i++){
32         for(int j=1 ; j<=n ; j++){
33                 cin >> a[i][j] ;    //第i个人做第j份工作的费用 
34                 x[j] = 0 ;
35         }
36         minExp+=a[i][i] ;
37     }
38 
39     backtrace(1,0) ;  //从第一个人开始遍历 
40     cout << minExp ; 
41 
42 return 0;    
43 }

算法第五章实践报告

 解空间为:{(1,2,3),(1,3,2),(2,1,3),(2,3,1),(3,1,2),(3,2,1)}

 约束函数:

x[j] == 0

即第j个人是否有工作
限界函数:
cexp < minExp
即当前费用小于最小费用

 

4、心得体会(对本次实践收获及疑惑进行总结)

刚开始做这道题想用数组交换元素的方法做,但是发现结果不对,其实这道题可以这样想:设置一个数组x[]来记录每个人是否有工作,每分配一份工作就从头遍历一次询问该元素i的x[i]是否为0,是则将该工作分配给他,再通过回溯来搜索出所有的情况,出来的代码比较简单。第二个要注意的是最小工作费用的初始化问题,由于遍历解空间树时第一条路径是(1,2,3)所以最小工作费用可以初始化为a[1][1]+a[2][2]+a[3][3]。这道题的解空间树属于排列树,也让我更加熟练掌握回溯法中排列树的算法思路和框架。