版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
第二题
题目描述:
有N辆车要陆续通过一座最大承重为W的桥,其中第i辆车的重量为w[i],通过桥的时间为t[i]。
要求:
第i辆车上桥的时间不早于第i-1辆车上桥的时间;
任意时刻桥上所有车辆的总重量不超过W。
那么,所有车辆都通过这座桥所需的最短时间是多少?
输入:
第一行输入两个整数N、W(1<=N、W <= 100000)。第二行输入N个整数 w[1] 到 w[N] (1 <= w[i] <=W )。第三行输入N个整数 t[1] 到 t[N] (1 <= t[i] <= 10000)。
输出:
输出一个整数,表示所有车辆过桥所需的最短时间。
样例输入
4 2
1 1 1 1
2 1 2 2
样例输出:
4
思路:
建立最小堆,用每辆车离开桥的时间排序,当前桥上的车重加下一辆该出发的车重小于W时,下一辆车出发(即加入堆中),每当堆顶的车下桥时,更新时间。
最小堆可以用优先队列实现。
扩展:
PriorityQueue(优先队列),一个基于优先级堆的无界优先级队列。
实际上是一个堆(不指定Comparator时默认为最小堆),通过传入自定义的Comparator函数可以实现大顶堆。
PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(); //小顶堆,默认容量为11
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(11,new Comparator<Integer>(){ //大顶堆,容量11
@Override
public int compare(Integer i1,Integer i2){
return i2-i1;
}
});
代码:
import java.util.HashMap;
import java.util.PriorityQueue;
import java.util.Scanner;
public class Duxiaoman2 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Scanner in = new Scanner(System.in);
int N = in.nextInt();
int W = in.nextInt();
int arrw[] = new int[N];
int arrt[] = new int[N];
for (int i = 0; i < N; i++) {
arrw[i] = in.nextInt();
}
for (int i = 0; i < N; i++) {
arrt[i] = in.nextInt();
}
Duxiaoman2 test = new Duxiaoman2();
System.out.println(test.mintime(arrw, arrt, W, N));
}
private int mintime(int[] arrw, int[] arrt, int W, int N) {
PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>();
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
int time = 0;
int w = 0;
int[] endtime = new int[N];
int i = 0;
int j = 0;
while (j < N) {
if (i < N && w + arrw[i] <= W) {
endtime[i] = arrt[i] + time;
map.put(endtime[i], map.getOrDefault(endtime[i], 0) + arrw[i]);
w = w + arrw[i];
minHeap.add(endtime[i]);
i++;
} else {
int emp = minHeap.peek();
time = minHeap.poll();
j++;
while (!minHeap.isEmpty() && emp == minHeap.peek()) {
minHeap.poll();
j++;
}
w = w - map.get(emp);
}
}
return time;
}
}