Проблема распределения задач (метод обратного отслеживания)

разработка алгоритма

описание проблемы

Существует n (n ≥ 1) задач, которые необходимо поручить для выполнения n людям. Каждую задачу можно поручить только одному человеку, и каждый человек может выполнить только одну задачу.
Стоимость выполнения j-го задания i-м человеком равна 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