题目链接: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. 【加密】Md5Util

    import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class Md5U ...

  2. transition,过渡效果

    语法: transtion:property time change-speed delay. 人话就是:属性(property )在多少秒内(time )通过什么样的速度(change-speed) ...

  3. uboot 如何向内核传递参数

    a.uboot 向内核传递的参数有两种类型 1.一个是bootargs 2.一个是环境参数, 而环境参数的设置靠的是 Y:\junda\JdLinuxApp\A1801_uboot\source\u- ...

  4. python - class类 (七) 三大特性 - 封装 结尾

    封装: # 封装 #第一层,类就是麻袋,本身就是一种封装 #第二层,类中定义私有的,至在类的内部使用,外部无法访问 #第三层,封装在于明确区分内外,使得类实现者可以修改封装内的东西二不影响外部调用者 ...

  5. SpringBoot2.x个性化启动banner设置和debug日志

    3.SpringBoot2.x个性化启动banner设置和debug日志 简介:自定义应用启动的趣味性日志图标和查看调试日志 1.启动获取更多信息 java -jar xxx.jar --debug ...

  6. 从Nexus私服下载和上传资源(一)

    从私服中下载资源 首先要明确将资源下载到哪里 找到maven 配置文件settings.xml 文件,添加如下配置:1.添加镜像配置:将所有访问外网仓库的请求指向私服: <mirror> ...

  7. Your Database is downloaded and backed up on....(腾讯云的mysql被攻击)

    今天发现自己的服务器被黑客攻击,自己的mysql服务器的库被删掉,并且新创了一个warning库,只有一个readme表.不知道原因,也许是自己再github上的项目暴漏了自己的密码,还要0.6比特币 ...

  8. Python基础-封装与扩展、静态方法和类方法

    一.封装与扩展 封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码:而外部使用者只知道一个接口(函数),只要接口(函数)名.参数不变,使用者的代码永远无需改变.这就提供一个 ...

  9. @Html.Action()

    背景 在这里主要想谈下mvc,最初几年都是用的webform,作为一个资深傻瓜程序员多年,后来到处听说mvc,终于在某天下定决心实验下mvc,其实关键还是在于easyui,因为它的请求数据方式和mvc ...

  10. 在try-catch机制优化IO流关闭时,OutputStreamWriter 数据流被截断

    1.前言 try-catch常规的格式是try{……}catch(){……}finallly{……},如果优化成try(……){……}catch(){……}finallly{……},此时流就可以自动关 ...