微软2017校招笔试题3 registration day

题目

It's H University's Registration Day for new students. There are M offices in H University, numbered from 1 to M. Students need to visit some of them in a certain order to finish their registration procedures. The offices are in different places. So it takes K units of time to move from one office to another.

There is only one teacher in each office. It takes him/her some time to finish one student's procedure. For different students this time may vary. At the same time the teacher can only serve one student so some students may need to wait outside until the teacher is available. Students who arrived at the office earlier will be served earlier. If multiple students arrived at the same time they will be served in ascending order by student number.

N new students need to finish his/her registration. They are numbered from 1 to N. The ith student's student number is Si. He will be arrived at H University's gate at time Ti. He needs to visit Pi offices in sequence which are Oi,1, Oi,2, ... Oi,Pi. It takes him Wi,1, Wi,2, ... Wi,Pi units of time to finish the procedure in respective offices. It also takes him K units of time to move from the gate to the first office.

For each student can you tell when his registration will be finished?

    N个新生入学,每个新生需要到M个office中的某些去办理手续,从一个office到另一个office路上需要花费时间K,第i个新生需要到p[i]个office办理手续(这p[i]个office分别为 o1, w1, o2, w2 ... o(p[i]), w(p[i]) 其中o为office,w为该新生在该office中办理手续需要花费的时间)。 
如果某个office正在办理别的同学的手续,则新到的同学需要在门口等待,如果两个同学同时到达office,则学号低的同学优先。 
    求出这N个同学各自的手续办理完成时间。

输入 
The first line contains 3 integers, N, M and K. (1 <= N <= 10000, 1 <= M <= 100, 1 <= K <= 1000)

The following N lines each describe a student.

For each line the first three integers are Si, Ti and Pi. Then following Pi pairs of integers: Oi,1, Wi,1, Oi,2, Wi,2, ... Oi,Pi, Wi,Pi. (1 <= Si <= 2000000000, 1 <= Ti <= 10000, 1 <= Pi <= M, 1 <= Oi,j <= M, 1 <= Wi,j <= 1000)

输出 
For each student output the time when he finished the registration.

解法

    参考讨论区别人的做法,将学生student进入office记为一个事件,且记录student到达office的时间,以及该student在该office中办理手续需要花费的时间。

struct Event{
    int student;
    int office;
    int begin;
    int duration;
}

 用优先队列维护一个个事件,这样事件就会按照时间排序,同时各个office接待同学是并行的关系,因此需要对每个office都维护该office可以接待新的同学的最早时间。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>  
#include<string>
#include<iostream>
#include<algorithm>
#include<functional>
#include<queue>
#include<vector>
#include<set>
#include<list>
#include<unordered_map>
#include<unordered_set>
#include<stack>
#include<map>
#include<algorithm>
#include<string.h>
using namespace std;
int N, M, K;
struct Student{
	int id;
	int arrive_time;
	int office_num;
	int finish_time;
	vector<pair<int, int>> register_offices;
};
Student students[10005];
struct Event{
	int student_idx;
	int office;
	int begin;
	int duration;
	Event(int s, int o, int b, int d) :student_idx(s), office(o), begin(b), duration(d){};	
};
struct Cmp{
	bool operator()(const Event& e1, const Event& e2){
		if (e1.begin == e2.begin)
			return students[e1.student_idx].id > students[e2.student_idx].id;
		return e1.begin > e2.begin;
	}
};
priority_queue<Event, vector<Event>, Cmp> pq;
int pre[105];
int pos[10005];
void Solve(){
	for (int i = 0; i < N; i++){
		pq.push(Event(i, students[i].register_offices[0].first, students[i].arrive_time + K, students[i].register_offices[0].second));
		pos[i] = 1;
	}
	memset(pre, -1, sizeof(pre));
	while (!pq.empty()){
		Event e = pq.top();
		pq.pop();
		int st = e.student_idx;
		if (pre[e.office] > e.begin){
			e.begin = pre[e.office];
		}
		int finish_time = e.begin + e.duration;		
		if (pos[st] == students[st].office_num){
			students[st].finish_time = finish_time;
		}
		else{
			int office = students[st].register_offices[pos[st]].first;
			int duration = students[st].register_offices[pos[st]].second;
			pq.push({ st, office, finish_time + K, duration });
			pos[st] ++;
		}
		pre[e.office] = finish_time;
	}
}
int main(){
	scanf("%d %d %d", &N, &M, &K);
	int p, o, w;
	for (int i = 0; i < N; i++){
		scanf("%d %d %d", &students[i].id, &students[i].arrive_time, &p);
		students[i].office_num = p;
		for (int j = 0; j < p; j++){
			scanf("%d %d", &o, &w);
			students[i].register_offices.push_back({ o, w });
		}
	}
	Solve();
	for (int i = 0; i < N; i++){
		printf("%d\n", students[i].finish_time);
	}
	return 0;
}

 

posted @ 2016-10-12 20:19  农民伯伯-Coding  阅读(2218)  评论(0编辑  收藏  举报