【分支限界法】任务分配问题 (nxn)

1.问题引入:

任务分配问题要求把n项任务分配给n个人,每个人完成每项任务的成本不同,要求分配总成本最小的最优分配方案。

设当前已对人员1~i分配了任务,并且花费了成本cur_cost,则限界函数可以定义:

lb=每个人对应的最小任务成本之和;

则最优解为:

bestcost=cur_cost)+lb;

任务和人员的编号均为1~n,解空间每一层对应一个人员的分配。

根结点对应人员0(虚结点),依次为人员1、2、…、n分配任务。

叶子结点对应人员n。

解向量为x:x[i]表示人员i分配任务编号。初始时所有元素值为0,表示没有分配。

临时标识数组work:work[i]=1表示任务i已经分配。初始时所有元素值为0,表示没有分配。

用best[Max]存放最优分配方案, bestcost(初始值为1e5)存放最优成本。

 2.代码:

#include<bits/stdc++.h>
using namespace std;
#define Max 2000
int n;
int cost[Max][Max];
int best[Max];
int bestcost=1e5;

struct node{
    int num;  //已分配人数
    int cur_cost;  //已计算成本
    int lb;  //当前下界
    int x[Max];  //第几个人分配第几个任务
    int work[Max];  //任务是否分配 0为未分配;
    bool operator<(const node& s) const{//定义排序规则
        return lb>s.lb;
    }
};

void bound(node&x){//计算下界函数
    int Min=0;
    for(int i=x.num+1;i<=n;i++){
        int mini=Max;
        for(int j=1;j<=n;j++){
            if(x.work[j]==0&&cost[i][j]<mini){
                mini=cost[i][j];
            }
        }
        Min+=mini;
    }
    x.lb=x.cur_cost+Min;
}
//注意:这里每一次计算完bound(y),并不能保证其最终取的cur_cost为lb,所以每一个扩展节点计算lb后就算它是最小的,也必须计算完所有的节点才能打印输出。
//(第一个达到叶子结点的并非全局最优解)与上题作业调度问题的区别是没有贪心计算下界,约束条件少一点。

void BFS(){
    priority_queue<node> Q;//创建优先队列;
    node x,y;
    //初始化根节点
    x.num=0;
    x.cur_cost=0;
    memset(x.x,0,sizeof(x.x));
    memset(x.work,0,sizeof(x.work));
    bound(x);
    Q.push(x);
    while(!Q.empty()){
        node z=Q.top();
        Q.pop();
        //到达叶子结点,及时更新最优成本bestcost值
        if(z.num==n){
            if(z.cur_cost<bestcost){
                bestcost=z.cur_cost;
                for(int j=1;j<=n;j++){
                    best[j]=z.x[j];
                }
            }
        }
        //计算新节点的各个值
        y.num=z.num+1;
        for(int i=1;i<=n;i++){
            if(z.work[i]) continue;
            //计算y的x[]值
            for(int j=1;j<=n;j++){
                y.x[j]=z.x[j];
            }
            y.x[y.num]=i;
            //计算y的work[]值
            for(int k=1;k<=n;k++){
                y.work[k]=z.work[k];
            }
            y.work[i]=1;
            //计算y的cur_cost和lb值;
            y.cur_cost=z.cur_cost+cost[y.num][i];
            bound(y);
            //判断并入队;
            if(y.lb<=bestcost){
                Q.push(y);
            }
        }
    }
}


int main(){
	cout<<"输入人员数/任务数大小: n"<<endl;
    cin>>n;
    printf("输入人员-任务值(%d x %d矩阵)\n",n,n);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cin>>cost[i][j];
        }
    }
    BFS();
    cout<<"最佳方案为:"<<endl;
    for(int i=1;i<=n;i++){
        printf("第%d个人分配%d个任务\n",i,best[i]);
    }
    cout<<"总成本为="<<bestcost<<endl;
    return 0;
}

3.运行截图:

菜鸟进化中.......

欢迎大家一起学习交流

  • 12
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
分支限界法是一种解决优化问题算法,可以用于解决分派问题。分派问题是指在有限的资源下,将一定数量的任务分配给一定数量的资源,使得总成本最小或者总效益最大。 分支限界法的基本思想是将原问题划分成若干个子问题,每个子问题都是原问题的一个限制条件或者一个分支。然后对每个子问题进行求解,得到一个最优解或一个上界。接着,根据上界对子问题进行剪枝,排除某些不可能得到最优解的子问题,以减少搜索空间。最终,通过搜索找到最优解。 在分派问题中,可以将每个任务看作一个子问题,通过枚举每个任务分配给每个资源的情况,得到一个上界,然后进行剪枝,排除一些不可能得到最优解的情况。最终,通过搜索得到最优解。 具体的分支限界法解决分派问题的步骤如下: 1. 将每个任务看作一个子问题,枚举每个任务分配给每个资源的情况,得到一个上界。 2. 对于每个子问题,计算一个下界,表示在当前情况下,得到最优解的最小成本或最大效益。 3. 根据上界和下界对子问题进行剪枝,排除一些不可能得到最优解的情况。 4. 对剩余的子问题进行搜索,得到最优解。 需要注意的是,分支限界法的效率与上界和下界的计算方法有关,如果上界和下界的计算方法不够准确或者复杂度过高,会导致算法的效率较低。因此,在实现分支限界法时,需要仔细选择上界和下界的计算方法,并根据具体情况进行优化。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值