任务分配问题(回溯法)

算法设计

问题描述

有n(n≥1)个任务需要分配给n个人执行,每个任务只能分配给一个人,每个人只能执行一个任务。
第i个人执行第j个任务的成本是c[i][j](1≤i,j≤n)。求出总成本最小的分配方案
在这里插入图片描述

解题思路

回溯法解题的一般步骤
(1)针对给定的问题确定问题的解空间树,问题的解空间树应至少包含问题的一个解或者最优解。
(2)确定结点的扩展搜索规则
(3)以深度优先的方式搜索解空间树,并在搜索的过程中可以采用减枝函数来避免无效搜索。其中,深度优先方式可以选择递归回溯或者迭代(非递归)回溯

通过将问题进行适当的转化,得出解空间树为排列树,这棵树每条完整路径都代表了一种解的可能。通过深度优先搜索这棵树,枚举每种可能的解的情况,找出能得到最小的花费结果。其中构造约束函数,可以删除一些不可能的解,从而大大提高程序效率

算法描述

(1)解空间
解空间为{x1,x2,x3,x4……,xn},其中xi=1,2,3,4……n,表示第i个人安排的任务
(2)解空间树
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include<cstring>

using namespace std;
#define MAXN 20
#define INF 9999

//定义问题
int n=4;
int a[MAXN][MAXN]={
    
    {
    
    0,0,0,0,0},{
    
    0,9,2,7,8},{
    
    0,6,4,3,7},{
    
    0,5,8,1,8},{
    
    0,7,6,9,4}}; 
//存储结果
int temp[MAXN];		//临时解 
int temp_cost=0;	//临时成本 
int best[MAXN];		//最优解 
int best_cost=INF;	//最优成本 
bool worker[MAXN];	//任务是否分配 
//深度优先遍历算法
void dfs(int i)
{
    
    
	if(i>n)							//遍历到叶子节点 
	{
    
    
		if(temp_cost<best_cost)		//临时成本<最优成本 
		{
    
    
			best_cost=temp_cost;	//更新最优成本 
			for(int j=1;j<=n;j++)
				best[j]=temp[j];	//更新最优解 
		}
	}
	else
	{
    
    
		for(int j=1;j<=n;j++)		//遍历任务 
			if(!worker[j])			//如果任务没有被选择,执行以下语句 
			{
    
    
				worker[j]=true;		//任务被选择 
				temp[i]=j;			//j任务分配给i人员 
				temp_cost+=a[i][j];	//临时成本 
				dfs(i+1);			//下一个人员分配任务		执行dfs(2),判断worker[1]=true已经被分配,执行j=2,第2个任务分配,直到i=4分配完成 
				worker[j]=false;	// ①执行worker[4]=false	② 
				temp[j]=0;			//①temp[4]=0 
				temp_cost=temp_cost-a[i][j];	//①减去第四个人员成本 
			}		
	}
 } 
 int main()
 {
    
    
 	memset(worker,0,sizeof(worker));//worker初始化为false 
 	dfs(1);							//从人员1开始 
 	for(int k=1;k<=n;k++)
		printf("第%d个人安排任务%d\n",k,best[k]);
	printf("总成本%d\n",best_cost);
	return 0;
 }

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_52108058/article/details/133905195