1、实践题目 :工作分配问题
2、问题描述
设有n件工作分配给n个人。将工作i分配给第j个人所需的费用为cij 。 设计一个算法,对于给定的工作费用,为每一个人都分配1 件不同的工作,并使总费用达到最小。
3、算法描述(包括解空间,画出测试样例的解空间树,剪枝(约束函数或限界函数)方法描述)
解空间是一个排列树,开一个二维数组a[i][j]来存工作i分配给第j个人所需的费用cij。第i层代表第i个任务,每个节点有n个分支。剪枝用到的约束条件是:x[i]!=1&&ct<bt。x[i]用来记录工人安排任务的情况,若值为1,则该工人已经安排了任务,不可再安排(不需要继续往下遍历),否则,可以安排工作。ct表示当前所花的时间,bt表示完成工作的最优时间,如果当前时间已经大于最优时间,则没有必要往下遍历了。
1 void backtrack(int t){ 2 if(t>n){ 3 if(ct<bt){ 4 bt = ct; 5 } 6 return; 7 } 8 for(int i=1;i<=n;i++){ 9 if(x[i]!=1&&ct<bt){ 10 ct += a[t][i]; 11 x[i] = 1; 12 backtrack(t+1); 13 x[i] = 0; 14 ct -= a[t][i]; 15 } 16 } 17 }
4、心得体会(对本次实践收获及疑惑进行总结)
这次编程的任务比较轻,只有两道题目,而且有一题是0-1背包是老师上课讲过的。第二题工作分配问题其实不难,刚一开始我和搭档都不谋而合地想到了旅行售货员的问题,拼命想怎么开一个数组维护这个排列树,但由于对旅行售货员问题掌握的不是很好,我们绞尽脑汁都没有想出来,最后果断放弃自己想解空间的处理,结果实际处理起来出乎意料地简单,真的是聪明反被聪明误。第一题有几个细节的地方处理起来比较繁琐,但因为原理都明白了,所以也是很快就解决了。这次实践让我感觉到了回溯法的神奇以及友好,希望以后可以多用回溯法去思考和处理问题,掌握了解空间的构建以及剪枝方法,这其实是一个强大但不难理解的方法。