题目描述
任务分配问题)将n项任务分配n个不同的人来完成,假定第i个人完成第j个任务所需的代价为cij,这样所有的cij就构成了一个代价矩阵。请用回溯法或分支限界法设计一个算法,在给定代价矩阵的情况下求出最佳分配方案,使完成这n项任务的总代价最小。
思路
由于每个人都必须分配到工作,在这里可以建一个二维数组cost[i][j],用以表示i号工人完成j号工作所需的费用。使用全局变量minprince记录最小花费,并将其初始值设置成INT_MAX。
使用c记录当前需要的花费,如果c已经大于minprince,这说明无需继续递归下去,起到剪枝的作用。当i的值等于n时,说明所有工人都有工作了,此时判断c的值是否小于minprince,若小于,则更新minprince的值。
使用一维数组visited标记工作j是否已分配工作,当visited[j]为false时,说明工作j未被分配,若为true时,则说明工作j已被分配作。当工作未被分配时,尝试将工作j分配给工人i,然后递归为工人i+1分配工作,同时更新c的值,当递归结束时,重置visited[j]的值,向上回溯,继续判断其他解是否更优。
代码
#include <iostream>
#include <climits>
using namespace std;
#define N 64
int n;
int minprice = INT_MAX;
int cost[N][N];
bool visited[N];
void backstrack(int i, int c);
int main(void)
{
cin >> n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> cost[i][j];
}
}
backstrack(0, 0);
cout << "最小代价为:" << minprice << endl;
return 0;
}
/**
* 为第 i 个人分配工作
*
* @param i: 第 i 个人
* @param c: 当前需要的总花费
* @return void
**/
void backstrack(int i, int c)
{
if (c > minprice) {
return ;
}
if (i == n) { // 最后一个人也被分配了工作
if (c < minprice) {
minprice = c;
}
return;
}
for (int j = 0; j < n; ++j) { // 尝试为工人 i 分配还未分配的工作
if (visited[j] == false) { // 工作 j 是否已分配出去
visited[j] = true;
backstrack(i + 1, c + cost[i][j]);
visited[j] = false; // 回溯
}
}
}