题目描述
Feynman有一天开了自己的公司,现在他有n件事情待解决,他手下恰好有n人。于是Feynman想要将这n件事分给n个人去做。已知每个人都可以做每件事,但是每个人做每件事的效率不同。下面给出每件事不同人做所需时间,请帮Feynman挑选合适的人去做事,使得总时间最短。
输入格式
第一行输入一个整数N,代表有N个员工,员工编号从1到N。(1<=N<=10)
接着输入一个N*N的二维矩阵,task[N][N],task[i][j]指的是第i项工作如果由j号员工完成所需的时间。、
0<=task[i][j]<=1000
输出格式
输出结果包含一个整数,代表所需要的最短时间(求和)。
样例输入
6 10 11 12 11 9 11 11 9 10 13 11 12 12 10 11 10 13 9 9 14 9 10 10 11 10 10 9 11 12 11 10 7 10 10 10 8
样例输出
54
思路1
递归思想(类似N皇后,不用判断对角线)因为一个任务对应一个人,所以每一行(一个任务)只能选择一个人(对应列)
对行进行dfs,每一列进行循环枚举,进入的对列进行标记,后面不能使用,sum增加;出来后清楚标记,sum减小。
边界条件即为l等于n,遴选最小的sum。
代码示例1
#include<iostream>
using namespace std;
int map[10][10];
int hang[10];
int lie[10];
int n,sum;
int Min=0xfffffff;
void dfs(int l)
{
if(l==n){
//cout<<sum<<"...."<<endl;
if(sum<Min) Min=sum;
return ;
}
for(int i=0;i<n;++i){
if(lie[i]==0){
sum+=map[l][i];
lie[i]=1;
dfs(l+1);
sum-=map[l][i];
lie[i]=0;
}
}
}
int main()
{
cin>>n;
for(int i=0;i<n;++i){
for(int j=0;j<n;++j){
cin>>map[i][j];
}
}
dfs(0);
cout<<Min<<endl;
return 0;
}
思路2
因为一个任务只能选择一个人,一个人不同重复做事,所以可以对于每个人做的事进行全排列,最后取最小值(和思路1的根源实际上是一样的,直接调用stl中的next_permutation)
可以用一个数组保存每项工作由几号员工完成,初始的化成{1, 2, 3, ... n}
,对于这个数组全排列枚举即可。
代码示例2
#include<iostream>
#include<algorithm>
using namespace std;
int map[10][10];
int arr[10];//全排列枚举
int main()
{
int n;
cin>>n;
for(int i=0;i<n;++i){
for(int j=0;j<n;++j){
cin>>map[i][j];
}
}
for(int i=0;i<n;++i) arr[i]=i;
int Min=0xfffff;
int sum;
do{
sum=0;
for(int i=0;i<n;++i){
sum+=map[i][arr[i]];
}
//cout<<sum<<"sf"<<endl;
if(sum<Min) Min=sum;
}while(next_permutation(arr,arr+n));
cout<<Min<<endl;
return 0;
}