1014 Waiting in Line (30 分) Java

题意 && 解题思路:

这道题脑子里要有一个动画。假如是两个窗口,每个窗口最多站两个人。

排队的人按照两个规则站队:

(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改写,但是思路应该没问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值