【DP】SMRTFUN

题目描述

“又肥又温顺,又大又笨,他们看起来那么傻,而且也不有趣……”

这些牛想要证明,他们是既有趣,又聪明的。为了这样做,Bessie组织了一个由牛组成的展览。她有N(1<=N<=100)头牛的情况:聪明程度Si(-1000<=Si<=1000)和有趣程度Fi(-1000<=Fi<=1000)。

Bessie必须选择一些牛来参展。牛的总的聪明值TS是所有参展牛的聪明值Si的和,总的有趣值TF是所有参展牛的有趣值Fi的和。Bessie希望能使TS和TF的和最大。但是,她仍然要求TF和TS都大于等于0,因为,如果其中一个小于0的话,对这个展出将是致命的。

所以,请帮助Bessie找到最大的TS和TF的和,而且这两个数都要非负。

输入

第一行,一个整数N,牛的个数。第2~N+1行,两个整数,依次是Si和Fi。

输出

仅一行,所求得的TS和TF的和

输入样例
5
-5 7
8 -6
6 -3
2 1
-8 -5
输出样例
8
样例说明

选择第1,3和4号牛。TS=-5+6+2=3,TF=7-3+1=5,所以,TS+TF=3+5=8。虽然,加上2号牛可以使总和变成10,但是,TF小于0,不符合要求。

说明
数据范围限制

1<=N<=100
(-1000<=Si<=1000)
(-1000<=Fi<=1000)


解题思路

由于每个牛只有选和不选两种情况,所以可以套用01背包

默认TS为体积,TF为价值

有些牛过于笨,有负数的情况,加上一个常数来保证数值不要低于0

我用了一维背包,如果牛是负数的时候, f [ j − T S [ i ] ] f[j - TS[i]] f[jTS[i]], j减负数就需要用到后面的f,所以要分两种情况来背包


Code
#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const int maxn = 400000;//防负常数
struct DT{
	int x, y;
}a[200];

int n;
long long ans, f[maxn * 2 + 100];

int main(){
	scanf ("%d", &n);
	for (int i = 1; i <= n; i++)
	     scanf ("%d%d", &a[i].x, &a[i].y);
	memset (f, -0x3f, sizeof(f));
	ans = f[0];
	f[maxn] = 0;
	for (int i = 1; i <= n; i++)
	{
		if (a[i].x< 0)//负数的情况下,因为会需要后面,所以先更新前面再更新后面
		{
			for (int j = 0; j <= maxn * 2 + a[i].x; j++)
			     f[j] = max(f[j - a[i].x] + a[i].y, f[j]);
	    }else {//正数的情况下,和普通背包一样
	    	for (int j = maxn * 2; j >= a[i].x; j--)
	    	     f[j] = max(f[j - a[i].x] + a[i].y, f[j]);
		}
	}
	for (int i = maxn; i <= maxn * 2; i++)
	     if (f[i] >= 0)
	         ans = max (ans, f[i] + i - maxn);//要记得把常数减去
	printf ("%lld", ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值