usaco 奶牛会展

来源:互联网 发布:计算机等级考试软件 编辑:程序博客网 时间:2024/04/29 19:24
奶牛想证明它们是聪明而风趣的。为此,贝西筹备了一个奶牛博览会,她已经对 N 头奶牛进行
了面试,确定了每头奶牛的智商和情商。
贝西有权选择让哪些奶牛参加展览。由于负的智商或情商会造成负面效果,所以贝西不希望出展
奶牛的智商之和小于零,或情商之和小于零。满足这两个条件下,她希望出展奶牛的智商与情商之和
越大越好,请帮助贝西求出这个最大值。
输入格式
• 第一行:单个整数 N,1 ≤ N ≤ 100
• 第二行到第 N + 1 行:第 i + 1 行有两个整数:Si 和 Fi,表示第 i 头奶牛的智商和情商,
−1000 ≤ Si,Fi≤ 1000
输出格式
• 单个整数:表示情商与智商和的最大值。贝西可以不让任何奶牛参加展览,如果这样做是最好
的,输出 0
样例输入
5
-5 7
8 -6
6 -3
2 1
-8 -5
样例输出
8
解释
选择第一头,第三头,第四头奶牛,智商和
为 −5+6+2 = 3,情商和为 7−3+1 = 5。再加
入第二号奶牛可使总和提升到 10,不过由于情商

和变成负的了,所以是不允许的


这道题刚拿着的时候是确实觉得十分恶心的 大犇勿嘲】 

看到题解的时候恍然大悟  这种题好像说是叫双肩包?! 不知道 反正 我们可以把它改成01背包

任意把S 或 F 当做容量 我是S】

所以01背包的模型就很容易看出来了

那么dp[ j ] 就表示 当智商为 j 时 情商最高值

因为S F 可能为 负数 所以我们可以把j当做坐标 整体右移 100 * 1000 位 把100000 当做原点

先贴上代码 再说注意事项

#include <iostream>#include <stdio.h>#include <cstdlib>#include <cstring>#include <conio.h>#define FOR( x , y ) for( int p = x ; p <= y ; p ++ )#define in( x ) scanf( "%d" , &x ) using namespace std ; int MOVE = 100000 ; int n , s[ 2005 ] , f[ 2005 ] , dp[ 400001 ], zd ; int main( ) {freopen( "smrtfun.in"  , "r" , stdin ) ; freopen( "smrtfun.out" , "w" , stdout ) ; in( n ) ; FOR( 1 , n ) {in( s[ p ] ) , in ( f[ p ] ) ;  if( s[ p ] > 0 ) zd += s[ p ] ; }FOR( 0 , MOVE * 2 + 2000  ) dp[ p ] = -2333333 ; dp[ MOVE ] = 0 ; FOR( 1 , n ) {if( s[ p ] >= 0 ) {for( int j = 200000 ; j >= s[ p ] ; j -- ) dp[ j ] = max( dp[ j ] , dp[ j - s[ p ] ] + f[ p ] ) ; }else {for( int j = 0 ; j <= 200000 + s[ p ] ; j ++ )dp[ j ] = max( dp[ j ] , dp[ j - s[ p ] ] + f[ p ] ) ; }}int ans = 0 ; FOR( MOVE , MOVE << 1 ) {if( dp[ p ] >= 0 ) ans = max( ans , dp[ p ] + p - MOVE ) ;} cout << ans ;  }


01背包枚举容量时从大到小 不知道见01背包 + 滚动数组 

这道题S可能为负数 所以我们从小到大枚举 ( 0 --  200000 + s[ p ] )

困惑了我好一会的还有个地方 背包的容量从 0 -- 200000 但是 j 不应该时奶牛的智商和吗 有没有可能 j 不是奶牛的智商和 ?

然后突然发现只需要把dp赋成一个很小的负数 然后把dp[ MOVE ] = 0 这个问题就解决了  不懂得自己多推推 

1 0
原创粉丝点击