- 欧浩 的博客
暑假打工
- @ 2025-7-17 19:07:36
暑假打工 题解
1.题目
注:一般认为一项任务当天就能完成,但只有在M天内领到报酬才算真正“做”了这项任务。所以在以下分析及代码中,一项任务在接受后第二天就能安排其他任务(即任务绝对意义上完成了),但做不做还要考虑能不能领到报酬。
2.开始做题
本人初始代码为价值9分的骗分,就不发了吧……
正解
其实是道简单的贪心,每天选择能完成的价值最大的任务,并将其完成就可以了。
具体的,需要将每项能完成的任务(即能领到报酬的)的工钱从大到小排序(这时候,要反向从最后一天枚举,逐步筛选能接受的任务),以待选择,每天选择一项任务,将所得报酬累加,就是答案。因为每天都会产生能完成的工作,如果每天都对任务的性价比排序,那时间直接爆炸,可以用优先队列,动态更新,时间复杂度会小很多。另外,如果你用结构体的形式存储每项任务的信息,想让它们排序的时候联动,需要重定义<符号,确保优先队列依据报酬进行排序。
话不多说上代码:
#include <bits/stdc++.h>
using namespace std;
const int TOP=1e5+5;
struct work
{
int a,b;
};
int n,m;
work t[TOP];
priority_queue<work> p;
int ans;
bool operator < (work one,work tow)
{
return one.b<tow.b;
}
bool cmp(work one,work tow)
{
return one.a<tow.a;
}
int main()
{
int f,k;
cin>>n>>m;
for(f=1;f<=n;f++)
cin>>t[f].a>>t[f].b;
sort(t+1,t+1+n,cmp);
k=1;
for(f=1;f<=m;f++)
{
while(k<=n&&t[k].a<=f)
{
p.push(t[k]);
k++;
}
if(!p.empty())
{
ans+=p.top().b;
p.pop();
}
}
cout<<ans;
return 0;
}

诚信做人,请勿抄袭