目录
题目
思路
代码
运行结果
题目
某车间需要用一台车床和一台×××加工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