回溯求任务安排问题

/*  任务安排问题: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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值