思路:
首先b>=0的项目不难处理,根据a值从小到大排序,能完成则r+=b[i]即可.关键是在于处理b<0的项目.
对于b<0的项目采用贪心策略:
先根据a值从大到小排序,每遍历到一个,就看它是否可以完成,如果可以,r+=b[i]并且标记i为完成状态. 如果不可以,看它是否可以替换之前已经完成的项目.假设j是某个之前已经完成的项目,i为当前不可完成项目,替换的条件为r-b[j]>=a[i]&&r-b[j]+b[i]>=0&&b[j]<=b[i],那么对于多个可以替换的项目,应该选哪个进行替换? 肯定是选替换后可以使r的值最大的那个,设i要替换j.替换完之后, 有一些不可完成的项目又变得可以完成了(最多只会有一个这样的项目,请仔细考虑,因为之前不可以完成的项目,肯定是因为它的b值太小了,它替换掉任意一个已经完成的项目都会使得r减小.而且这个项目必须要放在i的下一个去完成,如果放在i的前面,会导致未解决i之前的r值变得更小,就更无法解决i了,还有可能会影响i之前那些已经完成的任务.例如,j已经完成,i不能完成,现在i要替换j,有一个k是未完成的状态,我们现在想完成这个k必须将k放在i之后完成,如果k放在i之前完成,必定导致i不可能完成,因为k之所以是未完成状态,是因为k比j的b要小,所以如果不去完成j,而是先完成k,再去完成i,势必导致i不可以完成),所以再遍历i-1到1,找出之前没被完成但现在可以完成了并且使得剩余的r最大的那个项目,设置为完成状态.
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <time.h>
#include <map>
#include <set>
using namespace std;
struct Node{
int a,b;
}node[105],node1[105];
int book[105];
bool cmp(Node a,Node b){
return a.a<b.a;
}
bool cmp1(Node a,Node b){
return a.a>b.a;
}
int main(){
int n,r;
scanf("%d%d",&n,&r);
int cnt=0,cnt1=0;
int num=0;
for(int i=1;i<=n;i++){
int a,b;
cin>>a>>b;
if(b>=0){
node[++cnt].a=a;
node[cnt].b=b;
}
else{
node1[++cnt1].a=a;
node1[cnt1].b=b;
}
}
sort(node+1,node+cnt+1,cmp);
sort(node1+1,node1+cnt1+1,cmp1);
for(int i=1;i<=cnt;i++){
if(r<node[i].a){
break;
}
num++;
r+=node[i].b;
}
for(int i=1;i<=cnt1;i++){
if(node1[i].a<=r&&r+node1[i].b>=0){
num++;
r+=node1[i].b;
book[i]=1;
continue;
}
int id=0;
int maxn=r;
for(int j=i-1;j>=1;j--){
if(book[j]){
int t=r-node1[j].b;
if(node1[i].a<=t&&t+node1[i].b>=0){
if(maxn<t+node1[i].b){
maxn=t+node1[i].b;
id=j;
}
}
}
}
if(id==0)continue;
r=maxn;
book[i]=1;
book[id]=0;
id=0;
maxn=0;
for(int j=i-1;j>=1;j--){
if(book[j]==0){
if(r>=node1[j].a&&r+node1[j].b>=0){
if(id==0||maxn<r+node1[j].b){
id=j;
maxn=r+node1[j].b;
}
}
}
}
if(id==0)continue;
book[id]=1;
num++;
r=maxn;
}
printf("%d\n",num);
return 0;
}