题目链接:https://vjudge.net/contest/103424#problem/G

题目大意:

给出N头牛,每头牛都有智力值和幽默感,然后,这个题目最奇葩的地方是,它们居然可以是负数!!现在叫你求出其中的牛中,智力值总数和幽默感总数加起来最大的值,当然,智力值的总数必须大于等于零,幽默感总数也是。

解题思路:

转载于>>>大牛博客

对于每头牛,我们有两种选择,要么选,要么不选。看到这,就会觉得跟01背包很像,但是有 2 个变量来描述此状态的特征,智力,幽默感,并且他们可能是负数的。 
如果此题选择dp来解,我们要想办法把它转换成01背包。

下面转换01背包的方法。 
首先,下面的模板是 一维数组解背包问题 。

dp[i] = max(dp[i],dp[i-w[i]]+v[i])

首先,针对2个变量,智力,幽默感,我们定义i是前i头牛的智力总和,dp[i]存储的是此时智力总和为i时,幽默感总数的最大值。有人或许会问,题目叫我们求智力和幽默感的总数最大值啊,这dp最后得出的只是幽默感总数的最大值啊?没关系,求出整个dp后,将每个d[i] 和 i相加 看谁大就行了,别忘了,i就是智力总和。 

这一步是锁定变量。

开始下一步前,我们先来定义一下dp数组的大小吧。 
最多有100头牛,每个牛的智力范围在 -1000 – 1000 之间, 
那他们的总和就是 落在 -1000*100 – 100*1000这个区间了里,也就是我们的dp要开100*1000*2这么大了。然后模仿坐标系,在100*1000*2这些数里找一个原点,自然的,这个是对称的,很明显远点是100*1000也就是100000了。大于100000的,智力总和大于0,小于100000,智力总和小于0.

当然,这么大的数组我们不可能每个都访问到,这就要做个标记了,既然这里是求最大值,我们就把数组初始化为一个非常小的整数,inf = -100000000.

好了,接下来是关键的负数的处理了。负数的处理很明显和正数不同,但他们都是dp,只不过,处理方式发生了变化。

s[i] 第i头牛的智力
f[i]第i头牛的幽默感
for i : to N //表示第几头牛
if(智力是负数){
//处理
}
else if(智力是正数或者0){
//处理
}

先是,正数,每头牛有选与不选,仿照01背包

for(int v = **;v>=s[i];v--)
if(dp[v-s[i]]>inf)
dp[v] = max(dp[v],dp[v-s[i]]+f[i])

如果知道01背包的优化,上面就很简单了,逆序循环,保证每一个状态都能访问到上一个状态。

v = ;
dp [] = max(dp[],dp[-s[i]]+f[i])

s[i] > 0,5-s[i]很明显是小于 5的,此时,dp[5-s[i]]保存的还是上一个状态的值,所以我们可以放心大胆的用。

然后是判断条件,dp[v-s[i]]>inf,记得一开始我们把表示智力值总和的数组的初始化为inf吗?如果,dp[v-s[i]]<=inf,这意味着没有这个智力值没有用到,也就是dp[v] 这个是没有dp[v-s[i]]这个状态,既然没有我们就无视。

来看负数的

for(int v = s[i];v<**;v++)
if(dp[v-s[i]]>inf)
dp[v] = max(dp[v],dp[v-s[i]]+f[i])

仔细看会发现,其实就循环条件不同,为什么这样既可以呢? 
其实,可以参考01背包的空间优化和完全背包的空间优化。

不管是正数还是负数,我们都推,dp[v]时都要保证,它是由上一个状态的得来的。对于正数而言,上一个状态的智力总和是比当前状态小的。相反,对于负数而言,上一个状态的智力总和是比当前状态大的,s[i] < 0,v-s[i] > v,如果我们还是逆序循环的话,推dp[v]时,比他大的d[v-s[i]]早就改变了,不是上一个状态,那我们的递推就出现问题了,针对这个问题,我们正向循环就可以了。

最后,dp完后

来一个循环

ans = ;
for i:* to ** 智力总和要正数嘛
if(dp[i]>=)
ans = max(ans,i - * + dp[i]);

i-100*1000就等于此时的智力值总和了,因为我们让数组发生偏移了。

AC代码如下:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std; int dp[];
const int inf = << ; int main()
{
int n, s[], f[], i, j, ans;
while (~scanf("%d", &n))
{
for (i = ; i <= ; i++)
dp[i] = -inf;
dp[] = ;
for (i = ; i <= n; i++)
scanf("%d%d", &s[i], &f[i]);
for (i = ; i <= n; i++)
{
if (s[i]< && f[i]<)
continue;
if (s[i]>)
{
for (j = ; j >= s[i]; j--)//如果s[i]为正数,那么我们就从大的往小的方向进行背包
if (dp[j - s[i]]>-inf)
dp[j] = max(dp[j], dp[j - s[i]] + f[i]);
}
else
{
for (j = s[i]; j <= + s[i]; j++)//为负数则需要反过来
if (dp[j - s[i]]>-inf)
dp[j] = max(dp[j], dp[j - s[i]] + f[i]);
}
}
ans = -inf;
for (i = ; i <= ; i++)//因为区间100000~200000才是表示的整数,那么此时的i就是之前背包中的s[i],如果此时dp[i]也就
//是f[i]大于等于0的话,我们再加上s[i](此时为i),然后减去作为界限的100000,就可以得到答案
{
if (dp[i] >= )
ans = max(ans, dp[i] + i - );
}
printf("%d\n", ans);
}
return ;
}

2018-04-30

poj2184 Cow Exhibition【01背包】+【负数处理】+(求两个变量的和最大)的更多相关文章

  1. POJ-2184 Cow Exhibition(01背包变形)

    Cow Exhibition Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10949 Accepted: 4344 Descr ...

  2. [POJ 2184]--Cow Exhibition(0-1背包变形)

    题目链接:http://poj.org/problem?id=2184 Cow Exhibition Time Limit: 1000MS   Memory Limit: 65536K Total S ...

  3. POJ 2184 Cow Exhibition (01背包变形)(或者搜索)

    Cow Exhibition Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10342   Accepted: 4048 D ...

  4. POJ 2184 Cow Exhibition 01背包

    题意就是给出n对数 每对xi, yi 的值范围是-1000到1000 然后让你从中取若干对 使得sum(x[k]+y[k]) 最大并且非负   且 sum(x[k]) >= 0 sum(y[k] ...

  5. POJ 2184 Cow Exhibition (01背包的变形)

    本文转载,出处:http://www.cnblogs.com/Findxiaoxun/articles/3398075.html 很巧妙的01背包升级.看完题目以后很明显有背包的感觉,然后就往背包上靠 ...

  6. PKU 2184 Cow Exhibition 01背包

    题意: 有一些牛,每头牛有一个Si值,一个Fi值,选出一些牛,使得max( sum(Si+Fi) ) 并且 sum(Si)>=0, sum(Fi)>=0 思路: 随便选一维做容量(比如Fi ...

  7. POJ 2184 Cow Exhibition【01背包+负数(经典)】

    POJ-2184 [题意]: 有n头牛,每头牛有自己的聪明值和幽默值,选出几头牛使得选出牛的聪明值总和大于0.幽默值总和大于0,求聪明值和幽默值总和相加最大为多少. [分析]:变种的01背包,可以把幽 ...

  8. poj2184 Cow Exhibition(p-01背包的灵活运用)

    转载请注明出处:http://blog.csdn.net/u012860063 题目链接:id=2184">http://poj.org/problem?id=2184 Descrip ...

  9. POJ2184 Cow Exhibition 背包

    题目大意:已知c[i]...c[n]及f[i]...f[n],现要选出一些i,使得当sum{c[i]}和sum{f[i]}均非负时,sum(c[i]+f[i])的最大值. 以sum(c[i])(c[i ...

随机推荐

  1. luogu P3198 [HNOI2008]遥远的行星

    bzoj 洛谷 这题意是不是不太清楚 真正题意:求\[f_i=\sum_{j=1}^{\lfloor i*A \rfloor} \frac{M_i*M_j}{i-j}\] 似乎只能\(O(n*\lfl ...

  2. Linux 流量控制总结(TC)

    TC对带宽的描述:    mbps = 1024 kbps = 1024 * 1024 bps => byte/s    mbit = 1024 kbit => kilo bit/s.   ...

  3. SSH开发环境搭建

    断断续续学习hibernate也有一段时间了,在这里研究一下SSH开发环境的搭建过程,自己简单的搭建一个SSH的开发环境.采用maven搭建. 0.项目结构: 1.导包:(maven项目) pom.x ...

  4. Cpp读文件、CString转String、String转CString

    场景 C++读取文件 技术点 读取文件 fstream提供了三个类,用来实现c++对文件的操作.(文件的创建.读.写). ifstream -- 从已有的文件读入 ofstream -- 向文件写内容 ...

  5. 【转】Shell编程基础篇-下

    [转]Shell编程基础篇-下 1.1 条件表达式 1.1.1 文件判断 常用文件测试操作符 常用文件测试操作符 说明 -d文件,d的全拼为directory 文件存在且为目录则为真,即测试表达式成立 ...

  6. Salt Document学习笔记2

    配置文件需修改的内容及注意点: Edit the master config file: 1. Uncomment and change the user: root value to your ow ...

  7. python文件、文件夹操作OS模块

    转自:python文件.文件夹操作OS模块   '''一.python中对文件.文件夹操作时经常用到的os模块和shutil模块常用方法.1.得到当前工作目录,即当前Python脚本工作的目录路径: ...

  8. 了解的CAP和BASE等理论

    CAP,BASE和最终一致性是NoSQL数据库存在的三大基石.而五分钟法则是内存数据存储的理论依据.这个是一切的源头. 几个名词解释: 网络分区:俗称“脑裂”.当网络发生异常情况,导致分布式系统中部分 ...

  9. 卓越的目标检测器Pelee

    Densenet的改良—PeleeNET Pelee: A Real-Time Object Detection System on Mobile Devices 论文地址:https://arxiv ...

  10. 搭建ssh框架项目(一)

    一.创建web项目 二.导入jar包 三.创建数据库(MySQL) 四.建立javaBean对象(ElecText.java),属于持久层对象(PO对象) package com.cppdy.ssh. ...