作业分配问题——回溯

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

public class Test {
    private int n;//工人和作业的数量
    private int[] isworked;//记录对应的工作是否被做了
    private int[][] time;//记录初始每个工人做每件工作所花费的时间,行对应工人,列对应工作
    private int[][] record;//记录每次的分配情况
    private ArrayList<Integer> counts = new ArrayList<>();//记录各次分配情况对应的总的时间花费
    private int temp = 1;//记录分配的次数

    public static void main(String[] args) throws IOException {
        //输入测试编号
        System.out.println("请输入要测试的数据编号:1~6");
        Scanner input = new Scanner(System.in);
        int number = input.nextInt();

        Test test = new Test();
        test.readInit(number);//读取相应数据并初始化
        int count = 0;//初始的时间花费
        test.work(0,count);//回溯求取各个分配方案
        test.minCost();//求取各种分配方案的最小值即为所求
    }

    /**
     * 读取数据并初始化各个数组
     * @param number:文件的编号
     * @throws IOException
     */
    public void readInit(int number) throws IOException {
        BufferedReader reader = new BufferedReader(new FileReader(".\\input_assign04_0"+number+".dat"));
        this.n = Integer.parseInt(reader.readLine());//读取第一行的数据是作业或工人的个数
        isworked = new int[n];
        time = new int[n][n];
        record = new int[n][n];
        String line = "";
        int i = 0;
        System.out.println("每个工人做每项工作所需要花费的时间:");
        //读取数据并初始化每个工人做每个作业的时间数组,其他数组初始化默认为0
        while ((line = reader.readLine())!=null){
            String[] t = line.split(" ");
            for(int j=0;j<n;j++){
                time[i][j] = Integer.parseInt(t[j]);
                System.out.print(time[i][j]+" ");
            }
            i++;
            System.out.println();
        }
    }

    /**
     * 回溯求取各种分配方案
     * @param i:第i个工人
     * @param count:求取到当前所用的时间花费
     */
    public void work(int i,int count){
        if(i>=n){//当所有工人都有工作分配时,这时已经形成了一种方案
            this.counts.add(count);//将该方案的总花费添加到记录各种方案花费的数组中
            System.out.println("第"+(temp++)+"次分配结果是:");//输出该种方案
            for(int m = 0; m<record.length;m++){
                for(int n = 0; n<record[m].length; n++){
                    System.out.print(record[m][n]+" ");
                }
                System.out.println();
            }
            System.out.println("此次花费为"+count);
            return;
        }
        for(int j=0;j<n;j++){
            if(isworked[j]==0){//如果当前的工作没有被分配
                isworked[j] = 1;//就将该工作分配给当前的员工
                record[i][j] = 1;//记录第i个员工做第j个工作
                work(i+1,count+time[i][j]);//递归第(i+1)个员工分配工作
                isworked[j] = 0;//将记录置0,便于寻找其他的方案
                record[i][j] = 0;
            }
        }
    }

    /**
     * 求取最小花费
     */
    public void minCost(){
        Collections.sort(counts);//将各种方案的花费从小到大排序
        System.out.println("最少花费为:"+counts.get(0));//第一个值就是最小的时间花费
    }


}

回溯——深度优先

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值