Codeforces Round #579 (Div. 3)--F2. Complete the Projects (hard version)(贪心,dp)

题目链接

题意:
给定n个任务和一个初始评级r,对于每个任务都有一个评级要求,当且仅当达到评级要求及以上时才能去做任务,做完一个任务评级都会发生相应改变,增加或减少。可以跳过当前要完成的任务,去做其他任务,问这种条件下完成每一个任务之后评级都是非负数,且完成最后一个任务时评级也是非负数,所能完成的最多任务数。

分析:
之前的F1已经让我们解决了如何把所有任务排成尽可能多完成的顺序,所以可以照搬F1解法将任务排序,然后就是dp了,先写到这,改日更新。。。

int n,r;
class node{
	public:
	int a,b;
};
bool cmp(const node& x,const node& y){
	if(x.b>=0&&y.b>=0){
		if(x.a==y.a)
		return x.b>y.b;
		return x.a<y.a;
	}else
	if(x.b>=0||y.b>=0){
		return x.b>y.b;
	}else{
		if(x.a+x.b==y.a+y.b)
		return x.a>y.a;
		return x.a+x.b>y.a+y.b;
	}
}
void solve(){
	node s[n];
	int MAXN=r;
	REP1(i,n){
		cin>>s[i].a>>s[i].b;
	}
	sort(s,s+n,cmp);
	REP1(i,n){
		if(s[i].b<0)
		break;
		if(MAXN>=s[i].a&&s[i].b>=0)
		MAXN+=s[i].b;//所能达到的最高评级
	}
//	REP1(i,n)
//	cout<<s[i].a<<" "<<s[i].b<<endl;
	vector<VI> dp(2,VI(MAXN+1,-1));
	dp[0][r]=0;
	REP1(i,n){//i为当前第几个任务
		REP1(j,MAXN+1){//j表示当前拥有的评级
			if(s[i].b<0&&j-s[i].b>MAXN||s[i].b>=0&&j-s[i].b<0||s[i].b>=0&&s[i].a>j||s[i].b<0&&s[i].a>j-s[i].b||dp[i&1][j-s[i].b]==-1)
			dp[(i+1)&1][j]=dp[i&1][j];
			else{
				dp[(i+1)&1][j]=max(dp[i&1][j-s[i].b]+1,dp[i&1][j]);
			}
		}
	}
//	REP1(i,n+1){
//		REP1(j,MAXN+1)
//		cout<<dp[i][j]<<" ";
//		cout<<"\n";
//	}
	int ans=0;
	REP1(j,MAXN+1)
	ans=max(ans,dp[n&1][j]);
	cout<<ans<<endl;
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	while(cin>>n>>r)
	solve();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值