题意 && 解题思路:
这道题脑子里要有一个动画。假如是两个窗口,每个窗口最多站两个人。
排队的人按照两个规则站队:
(1)两个队伍一样长,选窗口编号小的站
(2)两个队伍长度不一样,选人少的站,一旦站队,就不再换队了。
动态规划问题。
按照题目给的数据,我们可以模拟一下排队的情况。
1) 假设还没到8点,但是顾客已经来齐了,已经站好队。
----------------
window[0]: 1 3
window[1]: 2 4
----------------2) 8:00到,开始服务,第一个人是1号顾客,他离开时为8:01,5号进入0号窗口
----------------
window[0]: 3 5
window[1]: 2 4
----------------3) 8:02,2号顾客服务完毕,6号进入1号窗口
----------------
window[0]: 3 5
window[1]: 4 6
----------------4) 8:06,4号顾客服务完毕,7号进入1号窗口
----------------
window[0]: 3 5
window[1]: 6 7
----------------5) 至此已经没有人在排队了,剩下的就是每个窗口服务完自己队伍里的人就行。
测试点:
有坑!!即使顾客16:59进入窗口,他需要60分钟完成服务,也要给他服务完,最后他会在17:59 离开,不能给他Sorry掉。(2,4)两个测试点都有这个坑。
import java.util.Scanner;
import java.util.LinkedList;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int m = input.nextInt();
int k = input.nextInt();
int q = input.nextInt();
//初始化窗口
Window windows[] = new Window[n];
for(int i=0; i<n; i++)
windows[i] = new Window(0, m);
//存放顾客服务完成的时刻
int complete[] = new int[k+1];
//初始化并存储顾客信息
Customer customerList[] = new Customer[k+1];
for(int i=1; i<=k; i++) {
int t = input.nextInt();
customerList[i] = new Customer(i, t);
}
//顾客先到,未到8:00已开始排队
for(int i=1; i<=n*m && i<=k; i++) {
int index = (i-1) % n;
windows[index].list.add(customerList[i]);
}
//8:00 开始服务
int waitNumber = n*m+1;
while(waitNumber <= k) {
Window servingWindow = getServeWindow(windows);
Customer c = servingWindow.list.removeFirst();
servingWindow.currentTime += c.processTime;
complete[c.id] = servingWindow.currentTime;
Window joinWindow = joinWindow(windows);
joinWindow.list.add(customerList[waitNumber]);
waitNumber++;
}
//当没有人在等的时候,服务区还可能在继续服务,处理剩下的顾客
for(int i=0; i<n; i++) {
while(!windows[i].list.isEmpty()) {
Customer c = windows[i].list.removeFirst();
windows[i].currentTime += c.processTime;
complete[c.id] = windows[i].currentTime;
}
}
//按要求输出
for(int i=0; i<q; i++) {
int queryNumber = input.nextInt();
int num = complete[queryNumber] ;
if(num - customerList[queryNumber].processTime < 540)
System.out.println(timeConversion(num));
else
System.out.println("Sorry");
}
input.close();
}
// public static void print(Window[] windows) {
// System.out.println("\n----------------");
// for(int i=0; i<windows.length; i++) {
// System.out.print("window[" + i + "]: ");
// for(Customer e: windows[i].list) {
// System.out.print(e.id+" ");
// }
// System.out.println();
// }
// System.out.println("----------------");
// }
public static Window getServeWindow(Window[] windows) {
int earlistWindowIndex = 0;
int minCurrentTime = Integer.MAX_VALUE;
for(int i=0; i<windows.length; i++) {
int currentTime = windows[i].currentTime + windows[i].list.getFirst().processTime;
if(minCurrentTime > currentTime) {
minCurrentTime = currentTime;
earlistWindowIndex = i;
}
}
return windows[earlistWindowIndex];
}
public static Window joinWindow(Window[] windows) {
int minCurrentLength = Integer.MAX_VALUE;
int index = 0;
for(int i=0; i<windows.length; i++) {
int curInLine = windows[i].list.size();
if(minCurrentLength > curInLine) {
minCurrentLength = curInLine;
index = i;
}
}
return windows[index];
}
public static String timeConversion(int minu) {
minu += 480;
int hour = minu/60;
minu -= hour*60;
String str = String.format("%02d:%02d", hour, minu);
return str;
}
static class Window{
int size;
int currentTime;
LinkedList<Customer> list;
public Window(int currentTime, int size) {
this.size = size;
this.currentTime = currentTime;
list = new LinkedList<>();
}
}
static class Customer{
int id;
int processTime;
public Customer(int id, int processTime) {
this.id = id;
this.processTime = processTime;
}
}
}
写在后面:
最后一个测试点没过,可能是因为java太慢了,以后再用C改写,但是思路应该没问题。