/* 任务安排问题:1. 假设需要将N个任务分配给N个工人同时去完成,每个人都能承担这N个任务,但费用不同。下面的程序用回溯法计算总费用最小的一种工作分配方案,在该方案中,为每个人分配1个不同的任务。
程序中,N个任务从0开始依次编号,N个工人也从0开始依次编号,主要的变量说明如下:
c[i][j]:将任务i分配给工人j的费用;
task[i]:值为0表示任务i未分配,值为j表示任务i分配给工人;
worker[k]:值为0表示工人k未分配任务,值为1表示工人k已分配任务;
mincost:最小总费用。
*/
#include<iostream>
#include<iomanip>
#include<vector>
using namespace std;
vector<int> work,task; // work[i]为0 表示工人i空闲,task[i]=j 表示把任务i安排给工人j 为-1 表示i没有被安排
vector< vector<int> >c; //c[k][i] 表示把任务K安排给工人i的费用
vector<int> temp; //用来存储最后任务安排的结果,思考其存在意义; !!因为task数组需要处理回溯条件,所以回溯往往需要额外变量来存储最终结果
int mincost=65535;//所有任务安排完的最小费用;
int task_n;
void Sign(int k,int cost)
{
if(k==task_n&& mincost>cost) //当最后一个任务分配完时,如果当前的费用小于最小费用,则跟新最小费用,并且存储任务安排结果
{
mincost=cost;
for(int j=0;j<task_n;j++)
temp[j]=task[j];
}
else//为任务k分配
{
for(int i=0;i<task_n;i++)
{
if(work[i]==0&&task[k]==-1) //找到一个工人,如果该工人空闲,且任务k还没有被安排,则将任务k分配给工人i
{
work[i]=1;
task[k]=i;
Sign(k+1,cost+c[k][i]); //安排下一个任务
task[k]=-1; //回溯处理
work[i]=0;
}
}
}
}
int main()
{
int n;
cout<<"请输入工作量:"<<endl;
cin>>n;
task_n=n; //工作量赋值
temp.resize(n);
work.resize(n);
task.resize(n);
c.resize(n);
for(vector< vector<int> >::iterator iiter=c.begin();iiter!=c.end();iiter++)
{
iiter->resize(n);
for(vector<int>::iterator iter=iiter->begin();iter!=iiter->end();iter++)
*iter=0;
}
for(int i=0;i<n;i++)
{
work[i]=0;
task[i]=-1;
for(int j=0;j<n;j++) // 各个数组的初始化
c[i][j]=i+j+1;
}
cout<<"开始时的任务安排费用如下:"<<endl;
for(i=0;i<n;i++)
{
for(int k=0;k<n;k++)
cout<<c[i][k];
cout<<endl;
}
/*for(i=0;i<n;i++)
cout<<work[i];
cout<<endl;
for(i=0;i<n;i++)
cout<<task[i];
cout<<endl;
for(i=0;i<n;i++)
{
for(int k=0;k<n;k++)
cout<<c[i][k];
cout<<endl;
}
*/
Sign(0,0); //从任务0 开始安排,开始的费用为0
/*
for(i=0;i<n;i++)
cout<<work[i];
cout<<endl;
for(i=0;i<n;i++)
cout<<task[i];
cout<<endl;
for(i=0;i<n;i++)
{
for(int k=0;k<n;k++)
cout<<c[i][k];
cout<<endl;
}
*/
for(i=0;i<n;i++)
cout<<"任务"<<i<<"分配给工人"<<temp[i]<<endl;
cout<<"最小总费用为:"<<mincost<<endl;
return 0;
}
程序中,N个任务从0开始依次编号,N个工人也从0开始依次编号,主要的变量说明如下:
c[i][j]:将任务i分配给工人j的费用;
task[i]:值为0表示任务i未分配,值为j表示任务i分配给工人;
worker[k]:值为0表示工人k未分配任务,值为1表示工人k已分配任务;
mincost:最小总费用。
*/
#include<iostream>
#include<iomanip>
#include<vector>
using namespace std;
vector<int> work,task; // work[i]为0 表示工人i空闲,task[i]=j 表示把任务i安排给工人j 为-1 表示i没有被安排
vector< vector<int> >c; //c[k][i] 表示把任务K安排给工人i的费用
vector<int> temp; //用来存储最后任务安排的结果,思考其存在意义; !!因为task数组需要处理回溯条件,所以回溯往往需要额外变量来存储最终结果
int mincost=65535;//所有任务安排完的最小费用;
int task_n;
void Sign(int k,int cost)
{
if(k==task_n&& mincost>cost) //当最后一个任务分配完时,如果当前的费用小于最小费用,则跟新最小费用,并且存储任务安排结果
{
mincost=cost;
for(int j=0;j<task_n;j++)
temp[j]=task[j];
}
else//为任务k分配
{
for(int i=0;i<task_n;i++)
{
if(work[i]==0&&task[k]==-1) //找到一个工人,如果该工人空闲,且任务k还没有被安排,则将任务k分配给工人i
{
work[i]=1;
task[k]=i;
Sign(k+1,cost+c[k][i]); //安排下一个任务
task[k]=-1; //回溯处理
work[i]=0;
}
}
}
}
int main()
{
int n;
cout<<"请输入工作量:"<<endl;
cin>>n;
task_n=n; //工作量赋值
temp.resize(n);
work.resize(n);
task.resize(n);
c.resize(n);
for(vector< vector<int> >::iterator iiter=c.begin();iiter!=c.end();iiter++)
{
iiter->resize(n);
for(vector<int>::iterator iter=iiter->begin();iter!=iiter->end();iter++)
*iter=0;
}
for(int i=0;i<n;i++)
{
work[i]=0;
task[i]=-1;
for(int j=0;j<n;j++) // 各个数组的初始化
c[i][j]=i+j+1;
}
cout<<"开始时的任务安排费用如下:"<<endl;
for(i=0;i<n;i++)
{
for(int k=0;k<n;k++)
cout<<c[i][k];
cout<<endl;
}
/*for(i=0;i<n;i++)
cout<<work[i];
cout<<endl;
for(i=0;i<n;i++)
cout<<task[i];
cout<<endl;
for(i=0;i<n;i++)
{
for(int k=0;k<n;k++)
cout<<c[i][k];
cout<<endl;
}
*/
Sign(0,0); //从任务0 开始安排,开始的费用为0
/*
for(i=0;i<n;i++)
cout<<work[i];
cout<<endl;
for(i=0;i<n;i++)
cout<<task[i];
cout<<endl;
for(i=0;i<n;i++)
{
for(int k=0;k<n;k++)
cout<<c[i][k];
cout<<endl;
}
*/
for(i=0;i<n;i++)
cout<<"任务"<<i<<"分配给工人"<<temp[i]<<endl;
cout<<"最小总费用为:"<<mincost<<endl;
return 0;
}