又是一道经典的贪心算法题目 。 乍看题目,想到了紫书一开始讲的区间问题(给定一些区间,选择尽可能多的不相交区间),和另一个经典问题:“活动安排” 的实质是一样的。
但是本题又和区间问题不同,因为区间起点未知,我们所知道的仅仅是等待时间和截至时间,但是其实贪心思想是一致的,即:尽可能的给后面的人留下更多时间,满足当前所用时间最少。 因此可以写出贪心算法 : 按照截至时间排序,将元素的消耗时间加到优先队列里,这样队首元素就是消耗时间最长的人,如果加上当前的人时间超过了他的截至时间,那么将队首元素(队列中消耗时间最多的人)删除。
不难发现对于该题,这样的做法是正确的。我们可以用反证法来加以证明:加入当前这个人之后,如果时间没有超出他的截止时间,那么这样是最好的。 如果超出了,那么肯定要牺牲一个人,为了给后面的人留出更多的时间,所以要删除消耗时间最长的人。
代码如下:
#include<bits/stdc++.h> using namespace std; const int maxn = 800000 + 5; int T,n; struct node { int l,r; }a[maxn]; bool cmp(node a,node b) { return a.r < b.r ; //** } int main(){ scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d%d",&a[i].l,&a[i].r); sort(a,a+n,cmp); priority_queue<int> q; int ans = 0,time = 0; for(int i=0;i<n;i++) { q.push(a[i].l); int t = q.top(); //加入当前的人 time += a[i].l; ans ++; if(time > a[i].r) { time -= t; q.pop(); ans --; //删除消耗时间最长的人,为后面的人留出更多的时间 } } printf("%d\n",ans); if(T) printf("\n"); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-12-28 18:31:41