题目描述
设有n件工作分配给n个人。将工作i分配给第j个人所需的费用为cij。试设计一个算法,为每一个人都分配一件不同的工作,并使总费用达到最小。
设计一个算法,对于给定的工作费用,计算最佳工作分配方案,使总费用达到最小
输入
由文件job.in给出输入数据。第一行有1个正整数n (1≤n≤20)。接下来的n行,每行n个数,第i行表示第i个人各项工作费用。
输出
将计算出的最小总费用输出到文件job.out。
样例输入 Copy
3 4 2 5 2 3 6 3 4 5
样例输出 Copy
9
先放上我时间超限(80%)的代码:(纯dfs搜索)
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#define N 25
using namespace std;
int c[N][N];
bool st[N];
int res=1e9;
int sum=0;
int n;
void dfs(int u)//遍历人,看看每个人挑啥
{
if(u>n)
{
res=min(res,sum);
return;
}
for(int i=1;i<=n;i++)
{//每个人挑物品
if(st[i]!=true)//物品没有被挑过
{
sum+=c[i][u];
st[i]=true;
dfs(u+1);
st[i]=false;
sum-=c[i][u];
}
}
return;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)//i件物品
for(int j=1;j<=n;j++)//j个人
cin>>c[i][j];
memset(st,false,sizeof st);
dfs(1);
cout<<res<<endl;
return 0;
}
剪枝之后的AC代码:(将还没搜索完但是金额已经超出最小方案的方案过滤掉)
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#define N 25
#define long long int
using namespace std;
int c[N][N];
bool st[N];
int res=1e18;
int sum=0,cost=0;
int n;
void dfs(int u,int sum)//遍历人,看每个人挑啥
{
if(u>n && sum<cost)//只要小了就可以更新
{
cost=sum;
return;
}
if(cost>=sum)//过滤以及超出之前金额的方案
{
for(int i=1;i<=n;i++)
{//每个人挑物品
if(st[i]!=true)
{
st[i]=true;
dfs(u+1,sum+c[i][u]);
st[i]=false;
}
}
}
return;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)//i件物品
{
for(int j=1;j<=n;j++)//j个人
{
cin>>c[i][j];
}
cost+=c[i][i];//随机设置一个可行的方案作为对照组
}
memset(st,false,sizeof st);//物品都没有被存过
dfs(1,0);//从第一个人开始搜索
cout<<cost<<endl;
return 0;
}