描述
现有N个物品,第i个物品有两个属性A_i和B_i。在其中选取若干个物品,使得sum{A_i + B_i}最大,同时sum{A_i},sum{B_i}均非负(sum{}表示求和)。
输入格式
第一行,一个整数,表示物品个数N。
接下来N行,每行两个整数,表示A_i和B_i。
接下来N行,每行两个整数,表示A_i和B_i。
输出格式
一个整数,表示最大的sum{A_i + B_i}。
测试样例1
输入
5
-5 7
8 -6
6 -3
2 1
-8 -5
输出
8
备注
N <= 100 , |A_i| <= 1000 , |B_i| <= 1000
【分析】
设f[i][j]表示前i位,在a目前值为j时的最大的b的和。
f[i][j]=max(f[i-1][j],f[i-1][j-a[i]]+b[i])。
由于C++不能以负数为数组坐标,所以统一向右平移100000位
res=max(i+f[n][i]),要满足i>=0,f[n][i]>=0。
【小结】当值小的时候,可以建立权值的数组。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,f[102][200002],ans=-1;
struct node{
int x,y;
}a[102];
int main(){
cin >> n;
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i].x,&a[i].y);
}
memset(f,-127,sizeof(f));
f[0][100000]=0;
for(int i=1;i<=n;i++)
for(int j=200000;j>=0;j--)
f[i][j]=max(f[i-1][j],f[i-1][j-a[i].x]+a[i].y);
for(int j=100000;j<=200000;j++){
if(f[n][j]>=0)
ans=max(ans,f[n][j]+j-100000);
}
printf("%d\n",ans);
return 0;
}