带后悔的贪心
首先,我们设一场电影的持续时间时间为,结束时间为
假设,我们决定好了要看哪些电影
且其中一种合法的看电影顺序为
那么,我们来贪心的化下式子:
假设,我们调换了看第i部和第i+1部电影的顺序后,使得当前的顺序不合法了,(前i-1部用的总时长为S)那么有:
当前方案:
因为调换后不合法,那么有:
可以推出:
也就是说,如果我们明确了要看哪些电影,一定存在一种合法方案,使得观看顺序为按由小到大的顺序看
那么,我们就可以先按由小到大排个序,再依次观看电影即可。
那么,现在就是一个简单的带后悔的贪心问题了,直接用个堆维护当前已选电影的最大持续时间即可。(因为有贪心策略:当前时间早的可以看的电影数量,一定不会小于当前时间晚的(Ps:这个可以用决策包容性证明))
代码:
#include<bits/stdc++.h> using namespace std; const int N=15e4+1; struct node{ int lon,ed; }t[N]; inline bool kkk(node x,node y){ return x.ed<y.ed; } priority_queue<int>s; int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%d%d",&t[i].lon,&t[i].ed); } sort(t+1,t+n+1,kkk); int now=0,ans=0; for(int i=1;i<=n;++i){ if(now<=t[i].ed-t[i].lon){ ++ans;now+=t[i].lon; s.push(t[i].lon); }else{ if(t[i].lon<s.top()){ now-=s.top();s.pop();now+=t[i].lon; s.push(t[i].lon); } } } printf("%d",ans); return 0; }