习题:Complete the Projects (hard version)(背包DP&贪心)
题目
思路
如果\(b_i\)为正,那么能选的一定会选
现在单独考虑\(b_i\)为负的情况
我们考虑对其进行排序,
设现在的rating为r
先选i
\(r>=a_i,r+b_i>=a_j\Rightarrow r>=max(a_i,a_j-b_i)\)
先选j
\(r>=a_j,r+b_j>=a_i\Rightarrow r>=max(a_j,a_i-b_j)\)
强行让第一种情况更优,这里的更优指的是对r的限制条件
\(max(a_i,a_j-b_i)<=max(a_j,a_i-b_j)\)
很明显有\(a_i<a_i-b_j,a_j<a_j-b_i\)
既可以把式子转换为
\(a_j-b_i<=a_i-b_j\)
\(a_j+b_j<=a_i+b_i\)
即将\(a_i+b_i\)从大到小排序再进行DP即可
代码
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
struct node1
{
int a,b;
friend bool operator < (const node1 &a,const node1 &b)
{
return a.a<b.a;
}
};
struct node2
{
int a,b;
friend bool operator < (const node2 &a,const node2 &b)
{
return a.a+a.b>b.a+b.b;
}
};
int n,r;
vector<node1> v1;
vector<node2> v2;
int bas;
int dp[7000005];
int main()
{
cin>>n>>r;
for(int i=1;i<=n;i++)
{
int a,b;
cin>>a>>b;
if(b>=0)
v1.push_back((node1){a,b});
else
v2.push_back((node2){a,b});
}
sort(v1.begin(),v1.end());
sort(v2.begin(),v2.end());
for(int i=0;i<v1.size();i++)
{
if(r>=v1[i].a)
{
r+=v1[i].b;
bas++;
}
}
memset(dp,-1,sizeof(dp));
dp[r]=0;
for(int i=0;i<v2.size();i++)
{
for(int j=v2[i].a;j<=r;j++)
{
if(dp[j]!=-1&&j+v2[i].b>=0)
{
dp[j+v2[i].b]=max(dp[j+v2[i].b],dp[j]+1);
}
}
}
int ans=0;
for(int j=r;j>=0;j--)
ans=max(ans,dp[j]);
cout<<bas+ans;
return 0;
}

浙公网安备 33010602011771号