Portals
主要要明白两点:
如果a和b都能够派兵前去把守c,且a>b,那么从a派兵去把守c是更优解
派兵要派往分数最大的地方,要把有限的派兵机会用在最值的地方
要实现这两步,要学会反悔贪心法,即如果当前兵力不足以攻打下一个城池,那么我们可以对之前派出去的兵进行“反悔”,即不派出军队,而在这个时候我们应该依次从分值小到分值大的城池进行反悔(可用一个优先队列进行维护),这样得到的结果才是最优的。
代码:
// Created by CAD on 2020/1/7.
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=5005;
int last[maxn],a[maxn],b[maxn],c[maxn];
priority_queue<int> value[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n,m,k;
cin>>n>>m>>k;
for(int i=1;i<=n;++i)
cin>>a[i]>>b[i]>>c[i],last[i]=i;
for(int i=1,u,v;i<=m;++i)
cin>>u>>v,last[v]=max(last[v],u);
for(int i=1;i<=n;++i)
value[last[i]].push(c[i]);
priority_queue<int,vector<int>,greater<int> > q;
ll sum=k;
for(int i=1;i<=n+1;++i) //边界为n+1的原因是要保证sum的值非负,且要得到最优值
{
while((!q.empty())&&sum<a[i])
sum++,q.pop();
if(sum<a[i])
return puts("-1");
sum+=b[i];
while(!value[i].empty())
sum--,q.push(value[i].top()),value[i].pop();
}
ll ans=0;
while(!q.empty())
ans+=q.top(),q.pop();
cout<<ans<<endl;
return 0;
}
几个毒瘤数据:
Input
3 2 1 0 0 20 0 0 10 0 0 5 2 1 3 1
Answer
20
Input
1 0 0 0 0 5
Answer
0
CAD加油!欢迎跟我一起讨论学习算法,QQ:1401650042