1 课程设计题目与要求
1.1设计题目:任务分配问题
1.2设计要求:
问题描述:
//有N个任务需要分配给n个人执行,一个任务对应一个人(意思是说,每个任务只分配给一个人,每个人只分配一个任务)
//对于每一对i,j=1,2,3......n来说,将j个任务分配给第i个人的成本是C[I,J];找出总成本最小的分配方案
2 总体设计
3 详细设计
3.1数据结构设计(或类设计)
本程序定义了一个主函数,用户可根据界面提示自行操作。由于要实现界面的回复,所以用了大量的函数调用,在控制用户的循环操作时采用了大量的for循环、do while语句、if else语句、return语句、switch语句等,其中涉及到多个递归函数表达式。
数据成员主要有成本矩阵,贪心成本,最低成本等内容,用户只需要在首页填写矩阵的大小,每个人员分配任务的成本即可。
Arr[][]; 成本矩阵
mincost; 每行最小值矩阵
greedcost[]; 贪心矩阵
temp[]; 每种组合方法的成本之和
k; temp数组中第k种成本
cost=0; 当前成本之和
y[]; 记录纵坐标前驱的数组
CreateArr(); 初始化成本矩阵
StarMin(); 初始化mincost[]数组
SetMin(); 填充mincost[]数组
SumMin(); mincost[]数组求和
StarTemp(); temp[]数组初始化
StarGreed(); 初始化贪心矩阵
SumOfGreed(); 贪心法求Arr[][]数组的近似最低成本
Recursion(); 递归调用函数
Back(); 回溯函数
3.2模块设计
3.2.1初始化成本矩阵函数,在整个程序开始运行之前,先构建一个二维数组,然后由用户输入具体的任务成本,等到整个循环结束,即可退出
3.2.2 初始化mincost[]矩阵函数,对于全局变量mincost[]函数,将Arr[]每一行先存入mincost[]数组中去,有利于后面的比较,并且找出最小值。
3.2.3 填充mincost[]数组函数,从Arr的每一行的第二个值开始比较,如果上一个的值比mincost[]对应的值小的话,就将mincost[]的值改为较小的数值。这样等到循环结束以后,mincost[]数组里面每一个对应的都是Arr每一行对应的最小值。即整个数组填充完毕。
3.2.4 mincost[]数组求和函数,就可以得出对应的成本下界。
3.2.5 temp[]数组初始化,temp数组是用于记录每一种可行的成本,即大于下界,且小于上界的人员分配方案。从而得到的结果存于temp数组中。第一个记录贪心矩阵所得的结果,即上界。
3.2.6初始化贪心矩阵函数,给贪心矩阵一个初始值。
3.2.7贪心法求Arr[][]数组的近似最低成本函数,在每一行选择出最合适的矩阵,作为放入贪心矩阵中,最后将贪心矩阵中的值相加,就可以得到贪心成本。
3.2.8递归调用函数,将Arr每一行的行数,人员数目,每一行所选的纵坐标作为参数传递进去,以是否全部寻找过全部元素作为出口,如果全部搜索了一遍,就可以到达出口。
3.2.9回溯函数,当递归函数的每一次往下搜寻失败的时候,利用回溯函数返回最近一个可执行行上去,继续进行搜寻。
4、运行结果
1、首先给出用户操作界面
2、用户根据提示选择相应功能
例如输入的人员为为4个人的话,则输入每个人员的任务成本,如图所示:
运行过后,我们可以得知整个成本矩阵的上界,下界,以及最优成本如下图所示:
5.详细代码:
#include
#include
using namespace std;
#define Max 9999
#define NUM 10000
//有N个任务需要分配给n个人执行,一个任务对应一个人(意思是说,每个任务只分配给一个人,每个人只分配一个任务)
//对于每一对i,j=1,2,3......n来说,将j个任务分配给第i个人的成本是C[I,J];找出总成本最小的分配方案
int Arr[1000][1000]; //成本矩阵
int mincost[1000]; //成本矩阵中每一行最小的成本
int greedcost[1000]; //贪心矩阵
int temp[NUM]; //每种组合方法的成本之和
int k=0; //temp数组中第k种成本
int cost=0; //当前成本之和
int y[1000]; //记录纵坐标前驱的数组,y[i]
void CreateArr(int number); //初始化成本矩阵
void StarMin(int number); //初始化mincost[]数组
void SetMin(int number); //填充mincost[]数组
int SumMin(int number); //mincost[]数组求和
void StarTemp(int number); //temp[]数组初始化
void StarGreed(int number); //初始化贪心矩阵
int SumOfGreed(int number); //贪心法求Arr[][]数组的近似最低成本
void Recursion(int i1,int j0,int j1,int number); //递归调用函数
int Back(int i,int j,int number); //回溯函数,清除本层痕迹,返回到上面最近的可执行的一行
int main()
{
int number,i=0,j=0,SumLow=0,SumUp=0; //任务(人)数量
cout << "请输入任务\\人员数量(n<=1000):" << endl;
cin >> number;
CreateArr(number); //创建二维成本矩阵
StarMin(number); //初始化mincost[]数组
SetMin(number); //填充mincost[]数组
SumLow=SumMin(number); //mincost[]数组求和,成本的下界
StarGreed(number); //初始化greedcost[]数组
SumUp=SumOfGreed(number); //贪心法求Arr[][]数组的近似最低成本,即成本的上界
for(int xy=0;xy>Arr[i][j];
}
}
}
void StarMin(int number) //初始化mincost[]数组
{
for(int n0=0;n0=number-1)
{
k++;
temp[k]=cost;
i=Back(i,j,number);
j=y[i];
}
else{
i++;
j=0;
while(greedcost[j]!=Max)
{
j++;
}
cost=cost+Arr[i][j];
y[i]=j;
greedcost[y[i]]=Arr[i][j];
}
}
else{
if(y[i]>=number-1)
{
i=Back(i,j,number);
j=y[i];
}
else{
i=Back(i,j,number);
j=y[i];
}
}
Recursion(i,y[i],j,number);
}
int Back(int i,int j,int number) //回溯函数,清除本层痕迹,返回到上面最近的可执行的一行
{
if(i==0)
{ //如果该行为第一行
if(y[i]==number-1)
{ //如果该元素是最后一个
y[i]++;
return i;
}
else{ //如果该元素不是最后一个
cost=cost-Arr[i][y[i]];
greedcost[y[i]]=Max;
y[i]++;
greedcost[y[i]]=Arr[i][y[i]];
cost=cost+Arr[i][y[i]];
return i;
}
}
else{ //如果不是第一行
y[i]=j;
while(greedcost[j]!=Max)
{
j++;
if(j>=number) break;
}
if(j