有n份作业分配给n个人去完成,每人完成一份作业。假定第i个人完成第j份作业需要花费cij时间, cij>0,1≦i,j≦n。试设计一个回溯算法,将n份作业分配给n个人完成,使得总花费时间最短。
C++实现:
/*
* Author: qinwu
* Created Time: 2017/4/30 22:45:25
* File Name: Solution.cpp
*/
#include <iostream>
#include <vector>
#include <limits.h>
#include <fstream>
#include <sstream>
using namespace std;
class Solution
{
public:
Solution():m_in("F:/gvim/jobassign/data.txt"), m_minCost(INT_MAX), m_njob(0){}
void readDataFromTxt();//从data.txt中读取数据
unsigned int getMinCost()//返回最小的开销
{
assign(0, 0);
return m_minCost;
}
void reset();//重置成员变量
~Solution(){m_in.close();}
private:
void assign(int k, unsigned int cost);//回溯法求解作业分配问题
//清除vector实际空间
template<class T>
void clearVector(vector<T>& vt)
{
vector<T> temp;
temp.swap(vt);
}
private:
ifstream m_in;
int m_njob;//作业数
unsigned int m_minCost;//最小开销
vector<vector<int> > m_c;//存储每个工人完成每个作业的时间
vector<bool> m_job;//标识作业是否被完成
};
void Solution::readDataFromTxt()
{
string line;
vector<int> temp;
int value;
while(!m_in.eof())
{
getline(m_in, line);
if(line[0] != '*')
{
stringstream s(line);
while(s >> value)
temp.push_back(value);
m_c.push_back(temp);
temp.clear();
}
else
break;
}
m_njob = m_c.size();
m_job = vector<bool>(m_njob, false);
}
void Solution::reset()
{
clearVector(m_job);
clearVector(m_c);
m_minCost = INT_MAX;
}
void Solution::assign(int k, unsigned int cost)
{
if(k >= m_njob && cost < m_minCost)
m_minCost = cost;//更新最小开销
else
{
for(int i=0; i < m_njob; ++i)//对当前工人k进行的作业的选择
{
if(!m_job[i] && cost+m_c[k][i] < m_minCost)
{
m_job[i] = true;
assign(k+1, cost+m_c[k][i]);//递归的对下一个工人进行作业选择
m_job[i] = false;
}
}
}
}
int main(void)
{
//测试
Solution t;
for(int i=0; i < 5; ++i)
{
t.readDataFromTxt();
cout << t.getMinCost() << endl;
t.reset();
}
}
data.txt中的实验数据:
实验结果: