CF1203F2 - Complete the Projects (hard version) 题解
题干
给定任务个数 和初始值 ,第 个任务至少需要 为 时才能做,完成后 会增长 ,每次完成任务后的能力值必须大于等于 ,最多能做多少个任务。
思路
一道贪心题,考虑 dp。
对第一个或最后一个阶段进行分类讨论,化原问题为子问题。——某老师
因为 ,显然,分类讨论从 入手,分正负两种。
对于 的任务,比较简单,即对应的 从小到大排序,当前能力值 就选上。
对于剩下的()任务,就需要解决“做第 个任务需要 的能力值,做完减少 (此时 为原 的绝对值),最多能做多少个任务”的问题。这时,dp 就派上用场了。 表示,做前 个任务,能力值为 时,最多能做几个任务。再优化压缩一下,可成为一维数组(不过还是两重循环)。
dp 前要先对任务进行排序,对于以上两种的 要分别用两个数组来装,对于装第一种的数组,以 从小到大排序,若相等则 更大者优先;对于第二种,则是以 更大者优先。
代码
#include<bits/stdc++.h>
using namespace std;
struct Node {
int need,val;
}yyx1[111],yyx2[111];
int l1,l2,aa,n,s,dp[66666],ans;
int main() {
memset(dp,-0x3f,sizeof(dp));
cin>>n>>s;
for(int i=1;i<=n;i++) {
int a,b;
cin>>a>>b;
if(b>=0) {
yyx1[++l1]=Node{a,b};
}
else {
yyx2[++l2]=Node{a,b};
}
}
sort(yyx1+1,yyx1+l1+1,[](Node a,Node b) {if(a.need==b.need)return a.val>b.val; return a.need<b.need;});
sort(yyx2+1,yyx2+l2+1,[](Node a,Node b) {return a.need+a.val>b.need+b.val;});
for(int i=1;i<=l1;i++) {
if(s>=yyx1[i].need) {
aa++,s+=yyx1[i].val;
}
}
for(int i=0;i<=s;i++)dp[i]=0;
for(int i=1;i<=l2;i++) {
for(int j=0;j<=60000;j++) {
if(j-yyx2[i].val<=60000&&j-yyx2[i].val>=yyx2[i].need) dp[j]=max(dp[j],dp[j-yyx2[i].val]+1);
ans=max(dp[j],ans);
}
}
cout<<ans+aa;
return 0;
}

浙公网安备 33010602011771号