回溯求任务安排问题

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
任务分配问题是一个经典的优化问题,通常使用回溯法进行解。这里给出一种基本的回溯任务分配问题的算法: 1. 定义状态表示:对于任务分配问题,我们可以使用一个长度为n的数组,其中第i个元素表示第i个任务被分配给了哪个人,初始状态为全0数组。 2. 定义状态扩展函数:状态扩展函数用于生成所有可能的下一步状态。对于任务分配问题,我们可以枚举当前未分配任务的人员,将当前未分配任务分配给该人员,生成新的状态。如果当前状态已经是一个合法解,则直接返回该解。 3. 定义剪枝函数:剪枝函数用于排除一些显然不可能达到最优解的状态,以减少搜索时间。对于任务分配问题,我们可以使用贪心策略,将当前未分配任务的人员按照某种规则排序,然后优先考虑分配给排名靠前的人员,如果发现当前状态已经不可能得到更好的解,则可以剪枝返回。 4. 实现回溯算法:使用上述状态表示、状态扩展函数和剪枝函数,实现回溯算法。回溯算法的基本思路是深度优先搜索所有可能的状态,直到找到一个合法解或者搜索完所有状态。 5. 优化算法效率:可以通过一些技巧来优化算法效率,例如使用启发式搜索、剪枝等方法。 总的来说,回溯法是一种基本的任务分配问题的方法,但是对于大规模问题,会面临指数级别的搜索空间,因此需要结合其他技术进行优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值