一、题目
给定一个数组arr,arr[i]代表第i号咖啡机泡一杯咖啡的时间,给定一个整数N,表示有N个人正在等着泡咖啡,每台咖啡机只能轮流泡咖啡,其次,只有一台可以洗咖啡杯的机器,一次只能洗一个咖啡杯,时间耗费a,洗完才能洗下一杯,每个咖啡杯也可以自己挥发干净,时间消耗b,咖啡杯可以并行挥发,假设所有人拿到咖啡后立刻喝完,返回从开始等待到所有咖啡杯都变干净的最短时间,给定3个参数,int[] arr,int a,int b,int N
二、题目分解
将题目分解成两大步骤来做:
2.1. 求出N个人喝完咖啡的最快时间,存储在数组中
public static class Machine{
public int timePoint;
public int workTime;
public Machine(int t,int w){
this.timePoint=t;
this.workTime=w;
}
}
public static class MachineComparator implements Comparator<Machine>{
@Override
public int compare(Machine o1, Machine o2) {
return (o1.timePoint+o1.workTime)-(o2.timePoint+o2.workTime);
}
}
public int minTime2(int[] arr,int n,int a,int b){
PriorityQueue<Machine> heap=new PriorityQueue<Machine>(new MachineComparator() );
for (int i = 0; i <arr.length ; i++) {
heap.add(new Machine(0,arr[i]));
}
int[] drinks=new int[n];
for (int i = 0; i < n; i++) {
Machine cur=heap.poll();
cur.timePoint+= cur.workTime;
drinks[i]= cur.timePoint;
heap.add(cur);
}
return bestTime(drinks,a,b,0,0);
}
2.2 求出洗完全部咖啡杯的最短时间
2.2.1 方法一:递归尝试
递归函数:
参数说明:
drinks 每一个人喝完的时间 wash 洗一杯需要的时间 air 自然挥发的时间
drinks[0,…index]下标已经洗干净了,不用管了 drinks[index…]所需的最短时间点返回 free
洗咖啡杯机器可再次使用的时间
终止条件:
index==drinks.length ,说明所有的杯子都洗干净了,直接返回0
普遍情况:
index号杯子有两种选择
(1)通过洗咖啡杯的机器清洗
开始洗的时间由,index喝完的时间和洗咖啡杯机器的可再用时间两者之间较大者决定,例如:index在7时间喝完咖啡,但洗咖啡杯的机器可在用的时间是10,那么index的杯子只能从10才能开始洗,反之,因为是同样的道理
除了index号杯子剩下杯子全部便干净的时间通过递归求出,因为index杯子使用洗咖啡的机器清晰,故下一次可在用的时间是index清洗干净了的时间
该情况下,所有杯子都变干净的的时间是,index变干净的时间和剩下所有杯子都变干净的时间的较大值
(2)自然挥发
index变干净的时间==喝完的时间+挥发的时间
剩下的杯子都变干净的时间,调用递归
该情况下,所有杯子都变干净的的时间是,index变干净的时间和剩下所有杯子都变干净的时间的较大值
返回两种选择所需时间的较小值
2.2.2 动态规划
业务限制模型,因为对于free这个参数的范围,我们无法直观得到。这时我们需要自己估计出来free的大小,通过分心我们直到,当所有的杯子都决定去洗时,此时的free将取到最大值.
public static int bestTimeDp(int[] drinks,int wash,int air){
int N= drinks.length;
int maxFree=0;
for (int i = 0; i < drinks.length; i++) {
maxFree=Math.max(maxFree,drinks[i])+wash;
}
int[][] dp= new int[N+1][maxFree+1];
//dp[N][...]=0; (index==drinks.length) return 0;
for(int index=N-1;index>=0;index--){
for(int free=0;free<=maxFree;free++){
int selfClean1=Math.max(drinks[index],free)+wash;
if(selfClean1>maxFree){
continue;
}
int restClean1=dp[index+1][selfClean1];
int p1= Math.max(selfClean1,restClean1);
//index号杯子决定挥发
int selfClean2=drinks[index]+air;
int restClean2=dp[index+1][free];
int p2=Math.max(selfClean2,restClean2);
dp[index][free]=Math.max(p1,p2);
}
}
return dp[0][0];
}