回溯法 解 作业分配问题

运行环境: Windows XP,(开发环境:VC6.0)
运行过程说明: jobAssignBacktrack.exe
输入源数据文件路径+文件名
在同目录下可以查看输出文件output.txt
★问题描述 有n份作业分配给n个人去完成,每人完成一份作业。假定第i个人完成第j份作业需要花费cij时间,cij>0,1≦i,j≦n。试设计一个回溯算法,将n份作业分配给n个人完成,使得总花费时间最短。
★格式输入 由文件input.txt给出输入数据。第一行有1 个正整数n (1≤n≤100)。
接下来的n行,每行n个数,表示工作费用。
★格式输出 将计算出的结果输出到文件output.txt。
★示例输入输出 5
50 87 62 56 92
43 22 98 57 36
1 5 97 96 43
58 62 27 73 27
60 71 38 71 95

144
工人: 1 执行任务: 4
工人: 2 执行任务: 2
工人: 3 执行任务: 1
工人: 4 执行任务: 5
工人: 5 执行任务: 3
★算法设计(包括算法设计过程中相关内容的说明、数据结构的选择、 算法详细描述及算法分析):
●1.设计说明:
算法中使用job[i]记录作业i是否已被分配,若被分配则置1,不必再搜索其分支;、
assign(int k,unsigned int cost) cost用来记录当前作业分配的开销,作为参数传递给下一层递归调用。
●2.算法设计:
●2.1数据结构:
#define N 100 //N表示最大任务数和工人数
int c[N][N]; //c[i][j] 表示工人i执行作业j所用的时间
unsigned int mincost = 65535; //设置的初始值,大于可能的费用
int task[N], //当前作业分配情况: 工人i执行task[i]
bestSolution[N], //最优作业分配情况: 工人i执行作业bestSolution[i]
job[N]; //记录作业是否已被分配给工人,1表示已分配,0为分配
int njob; //实际工作、工人数
主要操作:
void input(int& njob, int c[][N]); //读入工人、作业数njob,开销矩阵c[][N]
//初始化task,bestSolution,job,读入工人、作业数njob,开销矩阵c[][N]
void initData(int* task, int* bestSolution, int* job, int& njob, int c[][N]);
void assign(int k,unsigned int cost); //为工人k分配作业,cost:当前作业分配后的花费
//输出结果:mincost、作业分配情况
void outputResult(int minCost,int njob, int* bestSolution);
●2.2算法描述:
void assign(int k,unsigned int cost) //为工人k分配作业,cost:当前作业分配后的花费
{
int i;
if(k > njob && cost < mincost) //搜索至叶节点,判断是否更优
{
mincost = cost;
for(i=1; i<=njob; i++)
bestSolution[i] = task[i];
}
else
{
for(i=1;i<=njob;i++)
{
if(job[i]==0 && cost+c[k][i])//约束函数,job[i]==0则为被分配
{
job[i] = 1; task[k] = i;
assign(k+1,cost+c[k][i]);
job[i] = 0; task[k] = 0;
}
}
}
}
●2.3算法分析
本算法的最坏时间复杂度为:O(n!)
最坏空间复杂度为:O(n)

 //======================================================================= //jobAssign.cpp //将n份作业分配给n个人完成,使得总花费时间最短,回溯法 //by leo //5.13.2011 //======================================================================= #include <iostream> #include<fstream> #include<string> using namespace std; //———————————————————————– #define N 100 //N表示最大任务数和工人数 int c[N][N]; //c[i][j] 表示工人i执行作业j所用的时间 unsigned int mincost = 65535; //设置的初始值,大于可能的费用 int task[N], //当前作业分配情况:工人i 执行task[i] bestSolution[N], //最优作业分配情况: 工人i执行作业bestSolution[i] job[N]; //记录作业是否已被分配给工人,1表示已分配,0为分配 int njob; //实际工作、工人数 //———————————————————————– void input(int& njob, int c[][N]); //读入工人、作业数njob,开销矩阵c[][N] //初始化task,bestSolution,job,读入工人、作业数njob,开销矩阵c[][N] void initData(int* task, int* bestSolution, int* job, int& njob, int c[][N]); void assign(int k,unsigned int cost); //为工人k分配作业,cost:当前作业分配后的花费 //输出结果:mincost、作业分配情况 void outputResult(int minCost,int njob, int* bestSolution); //———————————————————————– void main() { initData(task, bestSolution, job, njob, c); assign(1,0); //从任务1开始分配 outputResult(mincost, njob,bestSolution); system(“pause”); } //———————————————————————– //读入工人、作业数njob,开销矩阵c[][N] //———————————————————————– void input(int& njob, int c[][N]) { string str; cout << “Please input the input file name” << “(input_assign04_00.txt~input_assign04_05.txt):/n”; cin >> str; ifstream fin(str.c_str()); if(!fin) { cout << “no such file,please check the file name!” <<endl; exit(0); } fin>>njob; for(int i = 1; i <= njob; i++) for (int j = 1; j <= njob; j++) fin >> c[i][j]; } //———————————————————————– //初始化task,bestSolution,job,读入工人、作业数njob,开销矩阵c[][N] //———————————————————————– void initData(int* task, int* bestSolution, int* job, int& njob, int c[][N]) { input(njob,c); for(int k =0; k <= njob; k++) { job[k] = 0; task[k] = 0; bestSolution[k] = 0; } } //———————————————————————– //为工人k分配作业,cost:当前作业分配后的花费 //———————————————————————– void assign(int k,unsigned int cost) { int i; if(k > njob && cost < mincost) { mincost = cost; for(i=1; i<=njob; i++) bestSolution[i] = task[i]; } else { for(i=1;i<=njob;i++) { if(job[i]==0 && cost+c[k][i]) { job[i] = 1; task[k] = i; assign(k+1,cost+c[k][i]); job[i] = 0; task[k] = 0; } } } } //———————————————————————– //输出结果:mincost、作业分配情况 //———————————————————————– void outputResult(int minCost,int njob, int* bestSolution) { cout<<“最小总费用:”<<mincost<<endl; for(int i=1; i<= njob;i++) cout<< “工人: “<< i <<” 执行任务: “<< bestSolution[i] <<endl; ofstream fout(“output.txt”); fout<<mincost<<endl; for(int j=1; j<= njob;j++) fout<< “工人: “<< j <<” 执行任务: “<< bestSolution[j] <<endl; } //=======================================================================

 

 

以下的代码稍作改变,用于c[i][j]表示作业i由工人j完成的情况

//======================================================================= //jobAssign.cpp //将n份作业分配给n个人完成,使得总花费时间最短,回溯法 //by leo //5.13.2011 //======================================================================= #include <iostream> #include<fstream> #include<string> using namespace std; //———————————————————————– #define N 100 //N表示最大任务数和工人数 int c[N][N]; //c[i][j] 表示作业i由人j执行所做的时间 unsigned int mincost = 65535; //设置的初始值,大于可能的费用 int task[N], //当前作业分配情况:i由工人task[i]执行 bestSolution[N], //最优作业分配情况: i由工人bestSolution[i]执行 worker[N]; //记录工人是否已被分配作业 int njob; //实际工作、工人数 //———————————————————————– //读入工人、作业数njob,开销矩阵c[][N] //———————————————————————– void input(int& njob, int c[][N]) { string str; cout << “Please input the input file name” << “(input_assign02_00.txt~input_assign02_01.txt):/n”; cin >> str; ifstream fin(str.c_str()); if(!fin) { cout << “no such file,please check the file name!” <<endl; exit(0); } fin>>njob; for(int i = 1; i <= njob; i++) for (int j = 1; j <= njob; j++) fin >> c[i][j]; } //———————————————————————– //读入工人、作业数njob,开销矩阵c[][N] //———————————————————————– void initData(int* task, int* bestSolution, int* worker, int& njob, int c[][N]) { input(njob,c); for(int k =0; k <= njob; k++) { //设置每个人任务由不同工人承担时的费用及全局数组的初值 worker[k] = 0; task[k] = 0; bestSolution[k] = 0; } } //———————————————————————– //测试:输出c[][N] //———————————————————————– void outputInitData(int c[][N]) { for(int i = 1; i <= njob; i++) { for (int j = 1; j <= njob; j++) cout << c[i][j] <<” “; cout<<endl; } } //———————————————————————– //k: 当前要分配的任务,cost:当前作业分配后的花费 //———————————————————————– void assign(int k,unsigned int cost) { int i; if(k > njob && cost < mincost) { mincost = cost; for(i=1; i<=njob; i++) bestSolution[i] = task[i]; } else { for(i=1;i<=njob;i++) //分配任务k { if(worker[i]==0 && cost+c[k][i]) { worker[i] = 1; task[k] = i; assign(k+1,cost+c[k][i]); worker[i] = 0; task[k] = 0; } } } } //———————————————————————– //输出结果:mincost、任务分配情况 //———————————————————————– void outputResult(int minCost,int njob, int* bestSolution) { cout<<“最小总费用:”<<mincost<<endl; for(int i=1; i<= njob;i++) cout<< “任务:”<< i <<” 由工人:”<< bestSolution[i] << “执行 ” <<endl; } //———————————————————————– void main() { initData(task, bestSolution, worker, njob, c); assign(1,0); //从任务1开始分配 outputResult(mincost, njob,bestSolution); for(int i = 1; i <= njob; i++) cout << bestSolution[i] << ” “; cout <<endl; } //=======================================================================

    原文作者:回溯法
    原文地址: https://blog.csdn.net/developinglife/article/details/6442787
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞