第五章实验报告
实践题目:
工作分配问题
问题描述:
设有n件工作分配给n个人。将工作i分配给第j个人所需的费用为cij 。 设计一个算法,对于给定的工作费用,为每一个人都分配1 件不同的工作,并使总费用达到最小。
输入格式:
输入数据的第一行有1 个正整数n (1≤n≤20)。接下来的n行,每行n个数,表示工作费用。
输出格式:
将计算出的最小总费用输出到屏幕。
输入样例:
在这里给出一组输入。例如:
3
10 2 3
2 3 4
3 4 5
输出样例:
在这里给出相应的输出。例如:
9
算法描述:
这道问题有点像N后问题进化版。
剪枝用了两种,一种是n后问题里面的不同行不同列(bound函数实现),一种是目前花销(money)与当前最优解(best)比较,(在调用bound之后就开始比了)
至于解空间和解空间树,我在下列的代码中加了两个money的输出,得到的解空间有(10,3,5),(10,4,4),(2,2,5),(2,4,3),(3,2,5),(3,3,3)
解空间树如图
我的代码如下:
代码里面cost、t、i等等都是从1开始的!!
1 #include <iostream> 2 using namespace std; 3 int best=10000; 4 bool bound(int k,int x[]){ 5 for(int j=1;j<k;j++) 6 if(x[j]==x[k]) 7 return false; 8 return true; 9 } 10 void backtrack(int t,int cost[][20+1],int n,int x[],int money){ 11 if(t>n){ 12 if(best>money) 13 best=money;//money为当前的花费,best为目前最优解 14 return ; 15 } 16 else{ 17 for(int i=1;i<=n;i++){ 18 x[t]=i; 19 if(bound(t,x)&&money<best){ 20 money+=cost[t][i]; 21 // cout<<money<<endl; 22 backtrack(t+1,cost,n,x,money); 23 money-=cost[t][i]; 24 // cout<<money<<endl; 25 } 26 } 27 } 28 } 29 int main(){ 30 int n; 31 cin>>n; 32 int cost[n+1][20+1]; 33 for(int i=1;i<=n;i++) 34 for(int j=1;j<=n;j++) 35 cin>>cost[i][j]; 36 int x[n+1]; 37 int money=0; 38 backtrack(1,cost,n,x,money); 39 cout<<best; 40 return 0; 41 }
心得体会:
回溯最大的问题,就是知道怎么写解空间树,不知道怎么用代码来写。。另外,c++学会class什么的真的买不了吃亏买不了上当,没看我传值快传疯了吗。