〖編程·C++〗回溯算法:排列树 - 工作分配问题

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

由文件input.txt给出输入数据。第一行有1 个正整数n (1≤n≤20)。接下来的n行,每行n个数,表示工作费用。将计算出的最小总费用输出到文件output.txt。例如:

     input.txt             output.txt

       3                    9

       10 2 3

       2 3 4

       3 4 5

源程序代码
 1  #include <fstream>
 2  #include <math.h>
 3  using namespace std;
 4  
 5  ifstream fin("f:\\gongzuofenpei\\input.txt");
 6  ofstream fout("f:\\gongzuofenpei\\output.txt");
 7  int **cost;
 8  bool *body;
 9  int cur_cost;
10  int min_cost;
11  int n;
12  
13  int output()
14  {
15      fout<<min_cost;
16      return 1;
17  }
18  
19  int backtrack(int t)
20  {
21      if(t>n)
22      {
23          if(cur_cost<min_cost)
24              min_cost=cur_cost;
25      }
26      else
27      {
28          for(int i=1;i<=n;i++)
29          {
30              if(body[i])
31              {
32                  body[i] = false;    
33                  swap(cost[t][1],cost[t][i]);
34                  cur_cost+=cost[t][1];
35                  
36                  if(cur_cost<min_cost) backtrack(t+1);
37  
38                  cur_cost-=cost[t][1];
39                  body[i] = true;
40                  swap(cost[t][1],cost[t][i]);
41              }
42          }
43      }
44      return 1;
45  }
46  
47  int main()
48  {
49      fin>>n;
50      cost = new int*[n+1];
51      for (int i=1;i<=n;i++)
52          cost[i] = new int[n+1];
53  
54      for (int i=1;i<=n;i++)//第i个任务
55          for(int j=1;j<=n;j++)//第j个人
56              fin>>cost[i][j];
57      body = new bool[n+1];
58      for (int i=1;i<=n;i++)
59          body[i] = true;
60      
61      //分配min_cost初值,为第i个任务分配给第i个人的总花费
62      min_cost = 0;
63      for(int i=1;i<=n;i++)
64          min_cost += cost[i][i];
65      cur_cost=0;
66  
67      backtrack(1);
68  
69      output();
70  
71      for(int i=1;i<=n;i++)
72          delete cost[i];
73      delete cost,body;
74      
75      fin.close(); 
76      fout.close();
77      
78      return 1;
79  }

 

 

增加输出一种分配方法的代码如下:

改进的代码
 1 #include <fstream>
 2 #include <math.h>
 3 using namespace std;
 4 
 5 ifstream fin("f:\\gongzuofenpei\\input.txt");
 6 ofstream fout("f:\\gongzuofenpei\\output.txt");
 7 int **cost;
 8 bool *body;
 9 int *best;
10 int *test;
11 int cur_cost;
12 int min_cost;
13 int n;
14 
15 int output()
16 {
17     fout<<"最低花费为:"<<min_cost<<endl;
18     for(int i=1;i<=n;i++)
19         fout<<""<<i<<"任务由"<<""<<best[i]<<"个人做,花费为"<<cost[i][best[i]]<<";"<<endl;
20     return 1;
21 }
22 
23 int backtrack(int t)
24 {
25     if(t>n)
26     {
27         if(cur_cost<min_cost)
28             min_cost=cur_cost;
29         for(int i=1;i<=n;i++)
30             best[i] = test[i];
31 
32     }
33     else
34     {
35         for(int i=1;i<=n;i++)
36         {
37             if(body[i])
38             {
39                 body[i] = false;    
40                 swap(cost[t][1],cost[t][i]);
41                 cur_cost+=cost[t][1];
42                 test[t]=i;
43                 if(cur_cost<min_cost) backtrack(t+1);
44 
45                 cur_cost-=cost[t][1];
46                 body[i] = true;
47                 swap(cost[t][1],cost[t][i]);
48             }
49         }
50     }
51     return 1;
52 }
53 
54 int main()
55 {
56     fin>>n;
57     cost = new int*[n+1];
58     for (int i=1;i<=n;i++)
59         cost[i] = new int[n+1];
60 
61     for (int i=1;i<=n;i++)//第i个任务
62         for(int j=1;j<=n;j++)//第j个人
63             fin>>cost[i][j];
64     body = new bool[n+1];
65     for (int i=1;i<=n;i++)
66         body[i] = true;
67 
68 
69 
70     //分配min_cost初值,为第i个任务分配给第i个人的总花费
71     min_cost = 0;
72     for(int i=1;i<=n;i++)
73         min_cost += cost[i][i];
74     cur_cost=0;
75     best = new int[n+1];
76     for(int i=1;i<=n;i++)
77         best[i] = i;
78     test = new int[n+1];
79     for(int i=1;i<=n;i++)
80         test[i] = 0;
81     backtrack(1);
82 
83     output();
84 
85     for(int i=1;i<=n;i++)
86         delete cost[i];
87     delete cost,body,test,best;
88     
89     fin.close();
90     fout.close();
91 
92     return 1;
93 }

 

 

转载于:https://www.cnblogs.com/shaoweinan/archive/2012/12/18/2823979.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值