这是题目链接:
任务序列传送门
题目大致意思就是小明接受了n个任务,想在任务剩余时间内获得尽可能多的奖励,给定n个任务的剩余时间和n个任务的奖励,求出获取奖励的最大值。这题两个做法:
1):按照奖励的降序排序,根据奖励的对应的时间获取到尽可能多的奖励,这种做法类似贪心。
2):这种做法我详细说一下,就是首先我们按照剩余时间排序,剩余时间少的排在前面,这个应该很好理解吧,就是剩余时间少的就要先做吗,对吧,从前向后选,但是如果遇到两个时间相同的,首先我们可能考虑和上一个时间段的时间差,然后将奖励值排序,选出前几个奖励值,但是我们考虑如果前一个时间段的奖励值比当前时间段的某个不可以取到的权值小,我们就需要从新更新数据,这时候立刻就应该想到建立一个优先队列来维护奖励的取值,这个队列需要用优先队列,而且需要保证队首元素为最小值,那么我们就可以立即判断当前元素是否可以被替换,直接在队列里清除就可以啦,这时候我们如何判断呢只需要判断当前时间和队列的元素个数进行比较,如果当前元素个数小于时间,一定可以入队列。这样简单点理解就是我们的队列始终维护的就是一个保证数据元素个数小于当前剩余时间,且最大的n个元素。
#include<bits/stdc++.h>
using namespace std;
struct node{
int x,y;
}e[1005];
bool cmp(node a,node b)
{
if(a.x!=b.x)return a.x<b.x;
else return a.y>b.y;
}
int main()
{
int n;
cin >> n;
for(int i=1;i<=n;i++)
{
cin>>e[i].x;
}
for(int i=1;i<=n;i++)
{
cin>>e[i].y;
}
sort(e+1,e+1+n,cmp);
priority_queue<int,vector<int>,greater<int> >q;
int sum=0;
q.push(e[1].y);
for(int i=2;i<=n;i++)
{
if(e[i-1].x==e[i].x)
{
if(e[i].y>q.top())
{
if(q.size()>=e[i].x){q.pop();}
//这个if保证如果size大于时间 就清楚队首元素放入一个更大的元素
q.push(e[i].y);
}
else
{
if(q.size()<e[i].x){q.push(e[i].y);}
//这里就是如果size小于当前时间 那么直接放入
}
}
else
{
q.push(e[i].y);
//这里如果二者时间不同后者一定大于前者 所以就直接压入队列
}
// cout << q.top() << endl;
}
while(!q.empty())
{
sum+=q.top();
q.pop();
}
cout << sum << endl;
}