车床零件加工调度问题

目录

题目

思路

代码

运行结果


题目

         某车间需要用一台车床和一台×××加工A,B,C,D4个零件。每个零件都需要先用车床加工,再用×××加工。车床和×××加工每个零件所需的工时(包括加工前的准备时间以及加工后的处理时间)如下表所示。

 若按ABCD顺序加工,需要多少小时完成所有零件加工?

若调整加工顺序,最少需要多少小时完成所有零件加工?

思路

我的思路非常简单,直接枚举每一个位置。也就是所谓的暴力递归

例子:

这里有四个零件ABCD分别要加工

第一个位置从ABCD里选择一个,我就选择B,那么就剩下ACD

第二个位置从ACD里选一个,我就选择A,那么就剩下CD

第三个位置从CD里选一个,我就选择C,那么就剩下D

第四个位置放只能放D

这个算法的复杂度及其高,如果没有算错的话应该是n!,但是我做了一些剪枝优化,复杂度会比这个要低很多。

这里分别有四种情况需要判断

1.第一次进入的时候怎么处理,这里只用处理一种情况

        ①第一种情况:

        xxx运行时间 = 车床处理第1个零件时间 + xxx处理第1个零件的时间

2.第n次进入的时候怎么处理(n>=2),这里需要处理三种情况

        ②第二种情况:

        车床:第i+1个零件加工完后 ;xxx:第i个零件正好加工完

        也就说xxx 是一直处于加工状态,没有空闲。

         整个过程加工时间也就是  xxx停止运行时间,也就是已经把车床给的零件都加工完了

         xxx运行时间= xxx处理完i个零件所需时间 + xxx加工第i+1个时间

        ③第三种情况:

          车床:第i+1个零件加工完后 ; xxx:还在加工第i个零件

        xxx运行时间= xxx处理完i个零件所需时间 + xxx加工第i+1个时间

        此时你会发现②和③的加工时间是一样的,所以在代码里把他合并起来

        

        ④第四种情况:

        车床:加工完第i+1个零件之前; xxx:已经把第i个零件加工完了,有空闲时间

        也就是说 车床在加工完第i+1个零件时候,xxx早就把第i个零件加工完了,并且空闲了一段时间

 xxx运行时间 = 车床加工前i+1个零件时间  + xxx加工第i+1个零件所需时间

代码

主函数:

public class Main {

   // arrayList  存储输入数据 相当于一个数组
    private static ArrayList<Work> arrayList = new ArrayList<Work>();
    //ans_src 用来存路径答案
    private static  ArrayList<String> ans_src=new ArrayList<String>();
    //  s 用来记录当前路径
    private  static String s="";
    // n 表示有多少个零件要加工   ans用来记录最短加工时长
    private static   int n=0,ans=-1;
    public static void main(String[] args) {

        Work w= new Work();
        arrayList.add(w);
        Scanner sc = new Scanner(System.in);
        n= sc.nextInt();

        //输入数据
        for (int i=1;i<=n;i++){
            Work work = new Work();
            int a,b;
            a=sc.nextInt();
            work.setA(a);
            b=sc.nextInt();
            work.setB(b);
            work.setFlag(true);
            arrayList.add(work);
        }
        //开始进行递归
        for (int i=1;i<=n;i++){
            //谁是第一个加工的? 每一个都要枚举一遍
            //i 表示 加工谁
            //1 表示 当前加工了多少个了
            // 0  0  前者表示车床加工时长  后者表示xxx加工时长
            //最后是记录加工路径
            //在记录路径的时候 我用了tran函数堆 i进行了转换,也就是说1对应A 2对应B...
            dfs(i,1, 0,0,""+tran(i));
        }
        System.out.println("所有可能如下::");
        for (int i = 0; i <ans_src.size(); i++) {
            System.out.println(ans_src.get(i));
            System.out.println("---------------------");
        }
        System.out.println("==================================");
        System.out.println("最短加工时长:"+ans);

        System.out.println("加工顺序:"+s);
    }

    /**
     *  暴力枚举每一个位置
     * @param pos 表示 加工谁
     * @param where 表示 当前加工了多少个了
     * @param A 表示车床加工时长
     * @param B 表示xxx加工时长
     * @param src 记录加工路径
     */
    public  static void  dfs(int pos,int where,int A,int B,String src){
        Work work = arrayList.get(pos);
        //先判断当前零件是否被加工过了,如果加工过了就退出
        //true 表示没被加工 false 表示被加工
        if (!work.isFlag())return;
        //标记当前零件被加工过了
        work.setFlag(false);
        int a= work.getA();//车床2   也就是车床在处理i+1个零件所需的时间
        int b= work.getB();//xxx2   也就是xxx在处理i+1个零件所需的时间

       if (where==1){//第一次进入的时候怎么处理,这里只用处理一种情况
           //第①种情况
           A=a;
           B=a+b;
       }
       else{//第n次进入的时候怎么处理(n>=2),这里需要处理三种情况
            if (A+a==B||A+a<B){
                //车床1+xxx1 == 车床1+车床2  或者 车床1+车床2 < 车床1+xxx1
                //第②种情况+第③种情况
                A+=a;
                B+=b;
            }
//            else if(A+a<B){//车床1+车床2 < 车床1+xxx1的情况
                //第③种情况
//                A+=a;
//                B+=b;
//            }
            else{// A+a>B  车床1+车床2 < 车床1+xxx1
                //第④种情况
                A+=a;
                B=A+b;
            }
       }

       for (int i=1;i<=n;i++){//接下来加工第i+1个位置,那选择谁?
           dfs(i,where+1,A,B,src+"---->"+tran(i));
       }

        //表示当前已经把 n个零件加工完了
        if (where==n){
            src+=";所需要的加工时间==>"+B;
            if (!ans_src.contains(src)){
                ans_src.add(src);
            }
            if(ans==-1){//遍历完后查看答案
                ans=B;
                s=src;

            }else{
                if (ans>B){
                    ans=B;
                    s=src;
                }
            }
        }
        //递归回溯
        //把当前零件的标记去了
        work.setFlag(true);

        }

    public static String tran(int pos){
        //对i进行转换 1->A  2 ->B 以此类推
        return Character.toString((char)('A'+pos-1));
    }
}

work类:

/**
 * @return
 */
public class Work {
    private  int A;//车床加工时间
    private  int B;//xxx加工时间
    private  boolean flag;//是否被加工
    // true 表示当前零件没被加工  false 表示当前零件已经被加工了

    public Work(int a, int b, boolean flage) {
        A = a;
        B = b;
        this.flag = flage;
    }

    public Work() {
    }

    public int getA() {
        return A;
    }

    public void setA(int a) {
        A = a;
    }

    public int getB() {
        return B;
    }

    public void setB(int b) {
        B = b;
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flage) {
        this.flag = flage;
    }

    @Override
    public String toString() {
        return "Work{" +
                "A=" + A +
                ", B=" + B +
                ", flag=" + flag +
                '}';
    }
}

运行结果

 输入:

4
8 6
4 7
6 2
6 5

输出:

所有可能如下::
A---->B---->C---->D;所需要的加工时间==>29
---------------------
A---->B---->D---->C;所需要的加工时间==>28
---------------------
A---->C---->B---->D;所需要的加工时间==>30
---------------------
A---->C---->D---->B;所需要的加工时间==>32
---------------------
A---->D---->B---->C;所需要的加工时间==>28
---------------------
A---->D---->C---->B;所需要的加工时间==>31
---------------------
B---->A---->C---->D;所需要的加工时间==>29
---------------------
B---->A---->D---->C;所需要的加工时间==>26
---------------------
B---->C---->A---->D;所需要的加工时间==>29
---------------------
B---->C---->D---->A;所需要的加工时间==>30
---------------------
B---->D---->A---->C;所需要的加工时间==>26
---------------------
B---->D---->C---->A;所需要的加工时间==>30
---------------------
C---->A---->B---->D;所需要的加工时间==>32
---------------------
C---->A---->D---->B;所需要的加工时间==>32
---------------------
C---->B---->A---->D;所需要的加工时间==>29
---------------------
C---->B---->D---->A;所需要的加工时间==>30
---------------------
C---->D---->A---->B;所需要的加工时间==>33
---------------------
C---->D---->B---->A;所需要的加工时间==>30
---------------------
D---->A---->B---->C;所需要的加工时间==>29
---------------------
D---->A---->C---->B;所需要的加工时间==>31
---------------------
D---->B---->A---->C;所需要的加工时间==>26
---------------------
D---->B---->C---->A;所需要的加工时间==>30
---------------------
D---->C---->A---->B;所需要的加工时间==>33
---------------------
D---->C---->B---->A;所需要的加工时间==>30
---------------------
==================================
最短加工时长:26
加工顺序:B---->A---->D---->C;所需要的加工时间==>26

进程已结束,退出代码0

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值