版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_38003892/article/details/84674562
1 问题描述
有n份作业分配给n个人去完成,每人完成一份作业。假定第i个人完成第j份作业需要花费cij时间, cij>0,1≦i,j≦n。试设计一个回溯算法,将n份作业分配给n个人完成,使得总花费时间最短。
2 算法实现
import java.io.*;
import java.util.*;
public class Demo {
public int n; // 记录工作人员数和作业数
public int isworked[]; // 记录第j号作业是否被做了
public int expense[][]; // 记录第i号工作人员做第j号工作所需的时间
public int res[][]; // 记录分配工作记录
public ArrayList<Integer> counts; // 记录每次分配的总花费
public int temp = 1; // 记录分配次数
public static void main(String[] args) throws Exception {
Demo demo = new Demo();
while(true){
demo.readdata();
int count = 0;
System.out.println("************分配结果************");
demo.work(0, count);
demo.returnlowres();
}
}
/**
* 读取测试数据
* @throws Exception
*/
public void readdata() throws Exception{
/*
* 选择测试文件序号
*/
System.out.println("共六组测试数据(1~6),请输入数据编号:");
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
/*
* 读取数据
*/
BufferedReader br = new BufferedReader(new FileReader("./src/input_assgin04_0" + num + ".dat"));
// 作业数以及工作人员数
this.n = Integer.parseInt(br.readLine());
System.out.println("*****************作业总数与工人总数*******************");
System.out.println(this.n);
// 初始化作业被做记录,默认为0,表示没有被做
this.isworked = new int[this.n];
for(int m = 0; m < this.isworked.length; m++){
this.isworked[m] = 0;
}
// 初始化每个工人做每项作业的花费信息
this.expense = new int[this.n][this.n];
System.out.println("*****************每个工人对应完成每个作业所需花费*******************");
for(int m = 0; m < this.n; m++){
String str = br.readLine();
for(int n = 0; n < str.split(" ").length; n++){
this.expense[m][n] = Integer.parseInt(str.split(" ")[n]);
System.out.print(this.expense[m][n] + " ");
}
System.out.println();
}
// 初始化分配工作表,默认都为0,表示没有分配
this.res = new int[this.n][this.n];
for(int m = 0; m < this.res.length; m++){
for(int n = 0; n < this.res[m].length; n++){
this.res[m][n] = 0;
}
}
// 创建花费记录
this.counts = new ArrayList<Integer>();
}
/**
* 开始计算所有分配花费
* @param i
* @param count
*/
public void work(int i, int count){
// 回溯
if(i>=this.n){
// 将本次分配结果的花费添加到花费集中
this.counts.add(count);
System.out.println("第" + this.temp + "次分配,此次花费为:" +count);
System.out.println("本次分配详情:");
for(int m = 0; m < this.res.length; m++){
for(int n = 0; n < this.res[m].length; n++){
System.out.print(this.res[m][n] + " ");
}
System.out.println();
}
return ;
}
// 如果当前工作没被做就分配给当前员工
for(int j = 0; j < this.n; j++){
if(this.isworked[j] == 0){
this.isworked[j] = 1;
this.res[i][j] = 1;
work(i+1, count + this.expense[i][j]);
this.isworked[j] = 0;
this.res[i][j] = 0;
}
}
}
/**
* 输出最少花费
*/
public void returnlowres(){
Collections.sort(this.counts);
System.out.println("******************最少花费********************");
System.out.println(this.counts.get(0));
}
}
3 数据输入文件格式
4 运行结果