【堆/优先队列】洗澡 bath

来源:互联网 发布:如何配眼镜知乎 编辑:程序博客网 时间:2024/05/07 20:08

洗澡

时限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++ Codehttp://blog.csdn.net/jiangzh7By 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;}





原创粉丝点击