@@ -873,235 +873,150 @@ func lcse(str1, str2 string) int {
873
873
例题:给定一个数组,代表每个人喝完咖啡准备刷杯子的时间,只有一台咖啡机,一次只能洗一个杯子,时间耗费a,洗完才能洗下一杯。每个咖啡杯也可以自己挥发干净,时间耗费b,咖啡杯可以并行挥发。返回让所有咖啡杯变干净的最早完成时间。三个参数:int[ ] arr , int a , int b(京东)
874
874
875
875
876
- ``` Java
877
- package class12 ;
876
+ ``` Go
877
+ package main
878
878
879
- import java.util.Arrays ;
880
- import java.util.Comparator ;
881
- import java.util.PriorityQueue ;
879
+ import " math"
882
880
883
- // 题目
884
881
// 数组arr代表每一个咖啡机冲一杯咖啡的时间,每个咖啡机只能串行的制造咖啡。
885
882
// 现在有n个人需要喝咖啡,只能用咖啡机来制造咖啡。
886
883
// 认为每个人喝咖啡的时间非常短,冲好的时间即是喝完的时间。
887
884
// 每个人喝完之后咖啡杯可以选择洗或者自然挥发干净,只有一台洗咖啡杯的机器,只能串行的洗咖啡杯。
888
885
// 洗杯子的机器洗完一个杯子时间为a,任何一个杯子自然挥发干净的时间为b。
889
886
// 四个参数:arr, n, a, b
890
887
// 假设时间点从0开始,返回所有人喝完咖啡并洗完咖啡杯的全部过程结束后,至少来到什么时间点。
891
- public class Code06_Coffee {
892
888
893
- // 方法一:暴力尝试方法
894
- public static int minTime1 (int [] arr , int n , int a , int b ) {
895
- int [] times = new int [arr. length];
896
- int [] drink = new int [n];
897
- return forceMake(arr, times, 0 , drink, n, a, b);
898
- }
899
-
900
- // 方法一,每个人暴力尝试用每一个咖啡机给自己做咖啡
901
- public static int forceMake (int [] arr , int [] times , int kth , int [] drink , int n , int a , int b ) {
902
- if (kth == n) {
903
- int [] drinkSorted = Arrays . copyOf(drink, kth);
904
- Arrays . sort(drinkSorted);
905
- return forceWash(drinkSorted, a, b, 0 , 0 , 0 );
906
- }
907
- int time = Integer . MAX_VALUE ;
908
- for (int i = 0 ; i < arr. length; i++ ) {
909
- int work = arr[i];
910
- int pre = times[i];
911
- drink[kth] = pre + work;
912
- times[i] = pre + work;
913
- time = Math . min(time, forceMake(arr, times, kth + 1 , drink, n, a, b));
914
- drink[kth] = 0 ;
915
- times[i] = pre;
889
+ // 方法二,每个人暴力尝试用每一个咖啡机给自己做咖啡,优化成贪心
890
+ func minTime2 (arr []int , n , a , b int ) int {
891
+ heap := &Machines{
892
+ Machines: make ([]*Machine, 0 ),
916
893
}
917
- return time;
918
- }
919
894
920
- // 方法一,暴力尝试洗咖啡杯的方式
921
- public static int forceWash (int [] drinks , int a , int b , int index , int washLine , int time ) {
922
- if (index == drinks. length) {
923
- return time;
895
+ // 构造洗碗机加入堆中
896
+ for i := 0 ; i < len (arr); i++ {
897
+ heap.Push (&Machine{
898
+ TimePoint: 0 ,
899
+ WorkTime: arr[i],
900
+ })
924
901
}
925
- // 选择一:当前index号咖啡杯,选择用洗咖啡机刷干净
926
- int wash = Math . max(drinks[index], washLine) + a;
927
- int ans1 = forceWash(drinks, a, b, index + 1 , wash, Math . max(wash, time));
928
-
929
- // 选择二:当前index号咖啡杯,选择自然挥发
930
- int dry = drinks[index] + b;
931
- int ans2 = forceWash(drinks, a, b, index + 1 , washLine, Math . max(dry, time));
932
- return Math . min(ans1, ans2);
902
+
903
+ drinks := make ([]int , n)
904
+ for i := 0 ; i<n; i++ {
905
+ cur := heap.Pop ().(*Machine)
906
+ cur.TimePoint += cur.WorkTime
907
+ drinks[i] = cur.TimePoint
908
+ heap.Push (cur)
933
909
}
934
910
935
- // 方法二:稍微好一点的解法
936
- public static class Machine {
937
- public int timePoint;
938
- public int workTime;
911
+ return processMachineTime (drinks, a, b, 0 , 0 )
912
+ }
939
913
940
- public Machine (int t , int w ) {
941
- timePoint = t;
942
- workTime = w;
943
- }
944
- }
914
+ // 方法二,洗咖啡杯的方式和原来一样,只是这个暴力版本减少了一个可变参数
915
+ // process(drinks, 3, 10, 0,0)
916
+ // a 洗一杯的时间 固定变量
917
+ // b 自己挥发干净的时间 固定变量
918
+ // drinks 每一个员工喝完的时间 固定变量
919
+ // drinks[0..index-1]都已经干净了,不用你操心了
920
+ // drinks[index...]都想变干净,这是我操心的,washLine表示洗的机器何时可用
921
+ // drinks[index...]变干净,最少的时间点返回
922
+ func processMachineTime (drinks []int , a , b , index , washLine int ) int {
923
+ if index == len (drinks) - 1 {
924
+ return int (math.Min (math.Max (float64 (washLine), float64 (drinks[index] + a)), float64 (drinks[index] + b)))
925
+ }
926
+
927
+ // 剩不止一杯咖啡
928
+ // wash是我当前的咖啡杯,洗完的时间
929
+ wash := int (math.Max (float64 (washLine), float64 (drinks[index]))) + a // 洗,index一杯,结束的时间点
930
+ // index+1...变干净的最早时间
931
+ next1 := processMachineTime (drinks, a, b, index + 1 , wash)
932
+ // index....
933
+ p1 := int (math.Max (float64 (wash), float64 (next1)))
934
+ dry := drinks[index] + b // 挥发,index一杯,结束的时间点
935
+ next2 := processMachineTime (drinks, a, b, index + 1 , washLine)
936
+
937
+ p2 := int (math.Max (float64 (dry), float64 (next2)))
938
+ return int (math.Min (float64 (p1), float64 (p2)))
939
+ }
945
940
946
- public static class MachineComparator implements Comparator<Machine > {
941
+ // Machines 洗咖啡的机器构造堆结构
942
+ type Machines struct {
943
+ Machines []*Machine
944
+ }
947
945
948
- @Override
949
- public int compare ( Machine o1 , Machine o2 ) {
950
- return (o1 . timePoint + o1 . workTime) - (o2 . timePoint + o2 . workTime);
951
- }
946
+ type Machine struct {
947
+ TimePoint int
948
+ WorkTime int
949
+ }
952
950
953
- }
951
+ func (c Machines ) Len () int {
952
+ return len (c.Machines )
953
+ }
954
954
955
- // 方法二,每个人暴力尝试用每一个咖啡机给自己做咖啡,优化成贪心
956
- public static int minTime2 (int [] arr , int n , int a , int b ) {
957
- PriorityQueue<Machine > heap = new PriorityQueue<Machine > (new MachineComparator ());
958
- for (int i = 0 ; i < arr. length; i++ ) {
959
- heap. add(new Machine (0 , arr[i]));
960
- }
961
- int [] drinks = new int [n];
962
- for (int i = 0 ; i < n; i++ ) {
963
- Machine cur = heap. poll();
964
- cur. timePoint += cur. workTime;
965
- drinks[i] = cur. timePoint;
966
- heap. add(cur);
967
- }
968
- return process(drinks, a, b, 0 , 0 );
955
+ // Less i对应的利润P的值大于j对应的值为true,则从大到小排序,即大根堆
956
+ func (c Machines ) Less (i , j int ) bool {
957
+ return (c.Machines [i].TimePoint + c.Machines [i].WorkTime ) < (c.Machines [j].TimePoint + c.Machines [j].WorkTime )
958
+ }
959
+
960
+ func (c Machines ) Swap (i , j int ) {
961
+ c.Machines [i], c.Machines [j] = c.Machines [j], c.Machines [i]
962
+ }
963
+
964
+ func (c *Machines ) Push (h interface {}) {
965
+ c.Machines = append (c.Machines , h.(*Machine))
966
+ }
967
+
968
+ func (c *Machines ) Pop () (x interface {}) {
969
+ n := len (c.Machines )
970
+ x = c.Machines [n-1 ]
971
+ c.Machines = c.Machines [:n-1 ]
972
+ return x
973
+ }
974
+
975
+ // 方法三:最终版本,把方法二洗咖啡杯的暴力尝试进一步优化成动态规划
976
+ func minTime3 (arr []int , n , a , b int ) int {
977
+ heap := &Machines{
978
+ Machines: make ([]*Machine, 0 ),
969
979
}
970
980
971
- // 方法二,洗咖啡杯的方式和原来一样,只是这个暴力版本减少了一个可变参数
972
-
973
- // process(drinks, 3, 10, 0,0)
974
- // a 洗一杯的时间 固定变量
975
- // b 自己挥发干净的时间 固定变量
976
- // drinks 每一个员工喝完的时间 固定变量
977
- // drinks[0..index-1]都已经干净了,不用你操心了
978
- // drinks[index...]都想变干净,这是我操心的,washLine表示洗的机器何时可用
979
- // drinks[index...]变干净,最少的时间点返回
980
- public static int process (int [] drinks , int a , int b , int index , int washLine ) {
981
- if (index == drinks. length - 1 ) {
982
- return Math . min(Math . max(washLine, drinks[index]) + a, drinks[index] + b);
983
- }
984
- // 剩不止一杯咖啡
985
- // wash是我当前的咖啡杯,洗完的时间
986
- int wash = Math . max(washLine, drinks[index]) + a;// 洗,index一杯,结束的时间点
987
- // index+1...变干净的最早时间
988
- int next1 = process(drinks, a, b, index + 1 , wash);
989
- // index....
990
- int p1 = Math . max(wash, next1);
991
- int dry = drinks[index] + b; // 挥发,index一杯,结束的时间点
992
- int next2 = process(drinks, a, b, index + 1 , washLine);
993
- int p2 = Math . max(dry, next2);
994
- return Math . min(p1, p2);
981
+ // 构造洗碗机加入堆中
982
+ for i := 0 ; i < len (arr); i++ {
983
+ heap.Push (&Machine{
984
+ TimePoint: 0 ,
985
+ WorkTime: arr[i],
986
+ })
995
987
}
996
988
997
- public static int dp (int [] drinks , int a , int b ) {
998
- if (a >= b) {
999
- return drinks[drinks. length - 1 ] + b;
1000
- }
1001
- // a < b
1002
- int N = drinks. length;
1003
- int limit = 0 ; // 咖啡机什么时候可用
1004
- for (int i = 0 ; i < N ; i++ ) {
1005
- limit = Math . max(limit, drinks[i]) + a;
1006
- }
1007
- int [][] dp = new int [N ][limit + 1 ];
1008
- // N-1行,所有的值
1009
- for (int washLine = 0 ; washLine <= limit; washLine++ ) {
1010
- dp[N - 1 ][washLine] = Math . min(Math . max(washLine, drinks[N - 1 ]) + a, drinks[N - 1 ] + b);
1011
- }
1012
- for (int index = N - 2 ; index >= 0 ; index-- ) {
1013
- for (int washLine = 0 ; washLine <= limit; washLine++ ) {
1014
- int p1 = Integer . MAX_VALUE ;
1015
- int wash = Math . max(washLine, drinks[index]) + a;
1016
- if (wash <= limit) {
1017
- p1 = Math . max(wash, dp[index + 1 ][wash]);
1018
- }
1019
- int p2 = Math . max(drinks[index] + b, dp[index + 1 ][washLine]);
1020
- dp[index][washLine] = Math . min(p1, p2);
1021
- }
1022
- }
1023
- return dp[0 ][0 ];
989
+ drinks := make ([]int , n)
990
+ for i := 0 ; i < n; i++ {
991
+ cur := heap.Pop ().(*Machine)
992
+ cur.TimePoint += cur.WorkTime
993
+ drinks[i] = cur.TimePoint
994
+ heap.Push (cur)
1024
995
}
1025
996
1026
- // 方法三:最终版本,把方法二洗咖啡杯的暴力尝试进一步优化成动态规划
1027
- public static int minTime3 (int [] arr , int n , int a , int b ) {
1028
- PriorityQueue<Machine > heap = new PriorityQueue<Machine > (new MachineComparator ());
1029
- for (int i = 0 ; i < arr. length; i++ ) {
1030
- heap. add(new Machine (0 , arr[i]));
1031
- }
1032
- int [] drinks = new int [n];
1033
- for (int i = 0 ; i < n; i++ ) {
1034
- Machine cur = heap. poll();
1035
- cur. timePoint += cur. workTime;
1036
- drinks[i] = cur. timePoint;
1037
- heap. add(cur);
1038
- }
1039
- if (a >= b) {
1040
- return drinks[n - 1 ] + b;
1041
- }
1042
- int [][] dp = new int [n][drinks[n - 1 ] + n * a];
1043
- for (int i = 0 ; i < dp[0 ]. length; i++ ) {
1044
- dp[n - 1 ][i] = Math . min(Math . max(i, drinks[n - 1 ]) + a, drinks[n - 1 ] + b);
1045
- }
1046
- for (int row = n - 2 ; row >= 0 ; row-- ) { // row 咖啡杯的编号
1047
- int washLine = drinks[row] + (row + 1 ) * a;
1048
- for (int col = 0 ; col < washLine; col++ ) {
1049
- int wash = Math . max(col, drinks[row]) + a;
1050
- dp[row][col] = Math . min(Math . max(wash, dp[row + 1 ][wash]), Math . max(drinks[row] + b, dp[row + 1 ][col]));
1051
- }
1052
- }
1053
- return dp[0 ][0 ];
997
+ if a >= b {
998
+ return drinks[n - 1 ] + b
1054
999
}
1055
1000
1056
- // for test
1057
- public static int [] randomArray (int len , int max ) {
1058
- int [] arr = new int [len];
1059
- for (int i = 0 ; i < len; i++ ) {
1060
- arr[i] = (int ) (Math . random() * max) + 1 ;
1061
- }
1062
- return arr;
1001
+ dp := make ([][]int , n)
1002
+ for i := 0 ; i < n; i++ {
1003
+ dp[i] = make ([]int , drinks[n - 1 ] + n * a)
1063
1004
}
1064
1005
1065
- // for test
1066
- public static void printArray (int [] arr ) {
1067
- System . out. print(" arr : " );
1068
- for (int j = 0 ; j < arr. length; j++ ) {
1069
- System . out. print(arr[j] + " , " );
1070
- }
1071
- System . out. println();
1006
+ for i := 0 ; i < len (dp[0 ]); i++ {
1007
+ dp[n - 1 ][i] = int (math.Min (math.Max (float64 (i), float64 (drinks[n - 1 ])) + float64 (a), float64 (drinks[n - 1 ] + b)))
1072
1008
}
1073
1009
1074
- public static void main (String [] args ) {
1075
- int [] test = { 1 , 1 , 5 , 5 , 7 , 10 , 12 , 12 , 12 , 12 , 12 , 12 , 15 };
1076
- int a1 = 3 ;
1077
- int b1 = 10 ;
1078
- System . out. println(process(test, a1, b1, 0 , 0 ));
1079
- System . out. println(dp(test, a1, b1));
1080
-
1081
- int len = 5 ;
1082
- int max = 9 ;
1083
- int testTime = 50000 ;
1084
- for (int i = 0 ; i < testTime; i++ ) {
1085
- int [] arr = randomArray(len, max);
1086
- int n = (int ) (Math . random() * 5 ) + 1 ;
1087
- int a = (int ) (Math . random() * 5 ) + 1 ;
1088
- int b = (int ) (Math . random() * 10 ) + 1 ;
1089
- int ans1 = minTime1(arr, n, a, b);
1090
- int ans2 = minTime2(arr, n, a, b);
1091
- int ans3 = minTime3(arr, n, a, b);
1092
- if (ans1 != ans2 || ans2 != ans3) {
1093
- printArray(arr);
1094
- System . out. println(" n : " + n);
1095
- System . out. println(" a : " + a);
1096
- System . out. println(" b : " + b);
1097
- System . out. println(ans1 + " , " + ans2 + " , " + ans3);
1098
- System . out. println(" ===============" );
1099
- break ;
1100
- }
1010
+ for row := n - 2 ; row >= 0 ; row-- { // row 咖啡杯的编号
1011
+ washLine := drinks[row] + (row + 1 ) * a
1012
+ for col := 0 ; col < washLine; col++ {
1013
+ wash := int (math.Max (float64 (col), float64 (drinks[row]))) + a
1014
+ dp[row][col] = int (math.Min (math.Max (float64 (wash), float64 (dp[row + 1 ][wash])),
1015
+ math.Max (float64 (drinks[row] + b), float64 (dp[row + 1 ][row]))))
1101
1016
}
1102
-
1103
1017
}
1104
-
1018
+
1019
+ return dp[0 ][0 ]
1105
1020
}
1106
1021
```
1107
1022
0 commit comments