题目链接: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. JS堆栈与拷贝

    一.堆栈的定义 1.栈是一种特殊的线性表.其特殊性在于限定插入和删除数据元素的操作只能在线性表的一端进行. 结论:后进先出(Last In First Out),简称为LIFO线性表.栈的应用有:数制 ...

  2. 超详细的Web前端开发规范文档

    规范目的为提高团队协作效率, 便于后台人员添加功能及前端后期优化维护, 输出高质量的文档, 特制订此文档. 本规范文档一经确认, 前端开发人员必须按本文档规范进行前台页面开发. 本文档如有不对或者不合 ...

  3. np.mat()和np.transpose

    例子: import numpy as np dataSet = [] with open('/home/lai/下载/20081023025304.plt') as fr: for line in ...

  4. sublime3添加python编译系统

    好记性不如烂笔头 为sublime3添加python编译系统,这里使用的anonconda2中的python.exe(即python2.7版本) 步骤: (1)打开sublime,打开“工具-> ...

  5. Libevent源码分析—event_base_dispatch()

    我们知道libevent是一个Reactor模式的事件驱动的网络库.   到目前为止,我们已经看了核心的event和event_base结构体的源码,看了初始化这两个结构体的源码,看了注册event的 ...

  6. 调用链系列二、Zipkin 和 Brave 实现(springmvc、RestTemplate)服务调用跟踪

    Brave介绍 1.Brave简介 Brave 是用来装备 Java 程序的类库,提供了面向标准Servlet.Spring MVC.Http Client.JAX RS.Jersey.Resteas ...

  7. saltstack中如何实现多个master来管理minion

    背景: 公司有多个部门,有一些机器有本部门的业务,这些机器也有其他部门的业务,所以本部门需要一个master服务器来管理这批机器,其他部门也需要一个master服务器来管理这个机器,所以就需要多个ma ...

  8. Javascript中Json对象与Json字符串互相转换方法汇总(4种转换方式)

    1.Json对象转Json字符串 JSON.stringify(obj); 2.Json字符串传Json对象 JSON.parse(str);//第一种 $.parseJSON(str);//第二种, ...

  9. sqlserver服务启动后停止,传递给数据库 'master' 中的日志扫描操作的日志扫描号无效

    电脑异常重启,导致SqlServer服务启动后,自动停止,在[计算机管理]-[事件查看器]-[windows日志]中进行查看系统错误日志,在[应用程序]下发现可能的错误信息有以下两条: 1.错误:传递 ...

  10. Webpack devServer中的 proxy 实现跨域

    Webpack dev server使用http-proxy解决跨域问题 文档资料 webpack关于webpack-dev-server开启proxy的官方介绍Vue-cli proxyTable ...