1、实践题目
工作分配问题
2、问题描述
设有n件工作分配给n个人。将工作i分配给第j个人所需的费用为cij 。 设计一个算法,对于给定的工作费用,为每一个人都分配1 件不同的工作,并使总费用达到最小。
输入格式:输入数据的第一行有1 个正整数n (1≤n≤20)。接下来的n行,每行n个数,表示工作费用。
输出格式:将计算出的最小总费用输出到屏幕。
输入样例:3
10 2 3
2 3 4
3 4 5
输出样例:9
3、算法描述(包括解空间,画出测试样例的解空间树,剪枝(约束函数或限界函数)方法描述)
(1)解空间
解空间为{x1,x2,x3,······,xn},其中xi=1,2,3,4···,n,表示第i个人安排的工作号。
(2)解空间树:以测试样例为例,解空间树如下:
(3)剪枝方法
1、每个工作是否已被分配,如已被分配,则不再分配给下一个人。
2、如果判断当前费用c已经大于之前算
(4)代码实现
1 #include <iostream> 2 using namespace std; 3 int n;//工作数量 4 int a[21][21];//工作费用 5 int flag[21];//标记是否已经分配过 6 int bestc = 0;//最少费用 7 8 void backtrack(int i,int c){ 9 if(i>n&&c<bestc){ 10 bestc = c; 11 return; 12 } 13 if(c<bestc) 14 for(int j=1;j<=n;j++){ 15 if(flag[j]==0){ 16 flag[j]=1; 17 backtrack(i+1,c+a[i][j]); 18 flag[j]=0; 19 } 20 } 21 } 22 23 24 int main(){ 25 cin>>n; 26 for(int i=1;i<=n;i++){ 27 for(int j=1;j<=n;j++){ 28 cin>>a[i][j]; 29 } 30 flag[i]=0;//初始都没有分配工作 31 bestc += a[i][i];//初始费用初始化为对角线之和 32 33 } 34 backtrack(1,0); 35 cout<<bestc; 36 return 0; 37 38 }
4、心得体会
(1)本次实践过程让我加深了对回溯算法的理解,特别是回溯的过程和限界函数,可能在上课的时候听老师讲是有点似懂非懂的,但是通过上机实践之后能很快发现自己不懂的地方在哪里,能比较快地发现自己的问题。
(2)不管是0-1背包还是这道工作分配,我觉得确定解空间树还是比较简单的,比较难的是回溯的过程还有限界函数的确定,需要在对解空间树的理解的基础上进行分析。还有就是不能死套框架,像我们在解工作分配这道题的时候,一开始觉得它与旅行售货员问题很像,所以就想套用旅行售货员的框架,结果就出了一点小问题,后来才发现这道题是没有旅行售货员那么复杂的,所以在解题的时候要懂得灵活应用,而不是一味地套框架。
原文地址:https://www.cnblogs.com/huangroumin/p/10164132.html
时间: 2024-10-31 08:23:19