现在的位置: 首页 > 综合 > 正文

【堆/优先队列】洗澡 bath

2014年02月08日 ⁄ 综合 ⁄ 共 1129字 ⁄ 字号 评论关闭

洗澡

时限1s

bath.pascal/c/cpp

 

【题目描述】

在某大学,洗澡是非常困难的事情。澡堂有m个房间,每个房间只能同时由一个人洗。当某个人来洗澡时,如果有空闲的房间,他就会随机选择一个去洗,否则会加入等待的队列,直到有新的空闲房间。现在有n个人先于你之前去洗澡,且已知每个人洗澡时持续的时间,求你何时能够开始洗澡。

【输入】

输入的第一行是n和m,分别表示在你之前去洗澡的人数和澡堂的房间数。

接下来的n行,每行有一个数,分别表示第i个人洗澡持续的时间ti。

【输出】

输出你何时能够洗澡,如果等待时间大于600输出-1。

【输入样例】
2 3

19

30

【输出样例】
4

【数据范围】

对于30%的数据,1<=n<=1000,1<=m<=1000

对于所有数据,1<=n<=100000,1<=m<=100000



这一题可以从分利用时间只有600这个信息,利用动态规划的递推来解决,时间复杂度O(600*N)


我使用的优先队列做的

在优先队列中维护结束时间(不是持续时间),每次把最小的 Q_top 弹出(洗完了),然后加入后一个人 x ,不过这个 x 要加上弹出 Q_top ,因为我们是维护的结束时间,而弹出 Q_top 就表示当前已经是 Q_top 这个时间了,而下一个要持续 x ,所以他会在 Q_top+x 时间结束

N个人加完后,输出队首的时间即可


C++ Code

/*
C++ Code

http://blog.csdn.net/jiangzh7

By Jiangzh
*/
#include<cstdio>
#include<queue>
using namespace std;

const int MAXN=100000+10;
int n,m;
int a[MAXN];
priority_queue<int,vector<int>,greater<int> > Q;
int t=0;

void read()
{
	freopen("bath.in","r",stdin);
	freopen("bath.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
}

void work()
{
	if(n<m) {printf("0\n");return;}
	int i=0;
	while(i<=n)
	{
		if(!Q.empty()&&Q.top()>600) {printf("-1");return;}
		while(Q.size()<m) Q.push(a[++i]+t);
		t=Q.top();Q.pop();
		while(!Q.empty()&&Q.top()==t) Q.pop();
	}
	printf("%d\n",t);
}

int main()
{
	read();
	work();
	return 0;
}



【上篇】
【下篇】

抱歉!评论已关闭.