思路1:
这个是非常好的一道贪心题目!
每个任务有一个最晚完成时间,用一个队列来维护到当前时间t的时候,一共完成了哪些任务。 遇到最晚完成时间大于t的,直接加入队列,与t相等的话,则置换一下,使得队列里面的值最大。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node {
int e;
ll w;
node ( int _e,ll _w ) {
e = _e;
w = _w;
}
bool operator < ( const node & a ) const {
return w>a.w;
}
};
bool cmp( const node &a,const node &b ) {
return a.e<b.e;
}
vector<node> vec;
int main() {
int n;
int m=0;
int e,w;
cin>>n;
for ( int i=0; i<n; i++ ) {
scanf("%d%d",&e,&w);
vec.push_back( node(e,w) ) ;
}
sort( vec.begin() ,vec.end(),cmp );
priority_queue<node> que;
int time = 1;
for ( int i=0; i<vec.size(); i++ ) {
if ( vec[i].e>=time ) {
que.push( vec[i] ) ;
time++;
} else {
if ( vec[i].w > que.top().w ) {
que.pop();
que.push( vec[i] );
}
}
}
ll ans = 0 ;
while ( que.empty()==0 ) {
ans += que.top().w;
que.pop();
}
cout<<ans<<endl;
return 0 ;
}
思路2:
这个思路我有想过,但是一直n2的复杂度,没想到可以用类似并查集的思想实现。
可以根据奖励的大小排序。
f[i] = j 代表 最晚完成时间可以在1-j时间内完成。
当我们选定过了一个活动,一定要从j到1进行赋值,不能抢占前面的时间。
#include <bits/stdc++.h>
using namespace std;
const int N = 50000+100;
struct node {
int cost;
int time;
node(){};
node ( int _c,int _t) { cost = _c; time = _t; };
};
int f[N];
node nodes[N];
int getTime( int x ) {
if ( x==0 ) return 0;
else if ( f[x]==x ) {
f[x] = x-1;
return x;
} else {
return f[x] = getTime( f[x] );
}
}
bool cmp( const node &a,const node &b ) {
if ( a.cost!=b.cost )
return a.cost>b.cost;
else
return a.time<b.time;
}
int main()
{
int n;
scanf("%d",&n);
for ( int i=1; i<=n; i++ )
scanf("%d%d",&nodes[i].time,&nodes[i].cost),f[i]=i;
sort( nodes+1,nodes+1+n,cmp );
long long ans =0 ;
for ( int i=1; i<=n ; i++ ) {
if ( getTime( nodes[i].time ) >0 )
ans += nodes[i].cost;
}
cout<<ans<<endl ;
return 0;
}