内容:有n(n≥1)个任务需要分配给n个人执行,每个任务只能分配给一个人,每个人只能执行一个任务。第i个人执行第j个任务的成本是c[i][j](1≤i,j≤n)。求出总成本最小的分配方案。
具体思路:
回溯法解题的一般步骤
(1)针对给定的问题确定问题的解空间树,问题的解空间树应至少包含问题的一个解或者最优解。
(2)确定结点的扩展搜索规则
(3)以深度优先的方式搜索解空间树,并在搜索的过程中可以采用减枝函数来避免无效搜索。其中,深度优先方式可以选择递归回溯或者迭代(非递归)回溯。
通过将问题进行适当的转化,得出解空间树为排列树,这棵树每条完整路径都代表了一种解的可能。通过深度优先搜索这棵树,枚举每种可能的解的情况,找出能得到最小的花费结果。其中构造约束函数,可以删除一些不可能的解,从而大大提高程序效率代码
#include <stdio.h>
#include <stdbool.h>
#include <limits.h>
#define MAX 50
int a[MAX][MAX]={{0},{0,9,2,7,8},{0,6,4,3,7},{0,5,8,1,8},{0,7,6,9,4}};//存成本
int n=4;//n个人,n个任务
int x[MAX];//临时解
int cost=0;//临时成本
int bestx[MAX];//最优解
int bestCost=INT_MAX;//最优成本
bool worker[MAX]={false};//j任务是否分配成员
void solve(int i)
{
if(i>n)
{
if(cost<bestCost)
{
bestCost=cost;
for(int j=1;j<=n;j++)
{
bestx[j]=x[j];
}
}
}
else
{
for(int j=1;j<=n;j++)
{
if(!worker[j])
{
worker[j]=true;
cost+=a[i][j];
x[i]=j;//任务j分配给i
solve(i+1);
//回溯
worker[j]=false;
cost-=a[i][j];
x[i]=0;
}
}
}
}
int main()
{
solve(1);
printf("最优解:\n");
for(int i=1;i<=n;i++)
{
printf("(%d,%d)",i,bestx[i]);
}
return 0;
}