本文转载,出处:http://www.cnblogs.com/Findxiaoxun/articles/3398075.html

很巧妙的01背包升级。看完题目以后很明显有背包的感觉,然后就往背包上靠。把s看成是空间,f看成是价值,转换成了01背包经典模型(没有想到,,,)。可,s是负值,这就涉及到一个问题,如果按照普通的01背包,(01背包的倒序原因请参看这个http://hi.baidu.com/findxiaoxun/item/9abf560127a155c091571868)

for(int i=;i<n;i++)
for(int v=maxv;v>=vi[i];v--)
dp[v]=max{dp[v],dp[v-vi[i]]+w[i]}

循环物品的时候,看第一件,在此题中,我们先假设最大空间为5,则2->5的值都为3,

然后i=1,循环第二件,v=5->3,而dp[5]=max{dp[5],dp[5+1]+4},背包空间为6的位置,我们假设预置为0,则dp[5]=4;dp[4]=max{dp[4],dp[4-(-1)]+4};则dp[4]=4+4=8;其实到这个值,我们已经看出,如果按照正常的逆序,s为负值的物品不只使用一次,这与题目的要求是相悖的。那么,正序考虑。读者可以自行推导,证明其可行性。

而我们发现,背包空间出现了负值,下限是-100*1000;上限是100*1000;一个很容易想到的方法就是,把100*1000,作为我们的数轴上的0点。也就是背包空间变成2*100*1000,不过在考虑的时候,以100*1000为原点,左边实际上是负值,右边是正值。则dp[i]是数据中左边一列s的和为s时的最大f值,而s+f=dp[i]+i-10000;

初始预置为-INF,dp[orgpoint]=0的目的是为了从0原点开始,而且,只放可以放的点。用一两个样例思考下就能明白。

算法的可行性,其实最大的要求就是符合01背包的特点,每个物品后只有一件,只放一次。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; const int MAXN=;
const int INF=0x3f3f3f3f;
const int MAXV=*(int)1e5;
int dp[MAXV+];
int s[MAXN],f[MAXN];
int n;
int main(){
int orgpoint=(int)1e5;
while(scanf("%d",&n)!=EOF){
for(int i=;i<n;i++)scanf("%d%d",&s[i],&f[i]);
for(int i=;i<=MAXV;i++)dp[i]=-INF;
dp[orgpoint]=;
for(int i=;i<n;i++){
if(s[i]>){//>0 then in reversed order
for(int j=MAXV;j>=s[i];j--)//this order ensure that we put every item just for one time
if(dp[j-s[i]]>-INF)
dp[j]=max(dp[j],dp[j-s[i]]+f[i]);
}else{//if negative number,have a look at the proof
for(int j=;j<MAXV+s[i];j++)
if(dp[j-s[i]]>-INF)
dp[j]=max(dp[j],dp[j-s[i]]+f[i]);
}
}
int ans=;
for(int i=;i<=;i++)
if(dp[i]>=&&dp[i]+i->ans)
ans=dp[i]+i-;
printf("%d\n",ans); }
return ;
}

代码参考http://www.cnblogs.com/kuangbin/archive/2012/09/14/2684929.html

最后附上本人的代码,其实差不多啦:

#include <iostream>
#include <stdio.h>
#include <string.h>
/*
AC
*/
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=;
const int V=;
int s[maxn],f[maxn];
int dp[V*+];
int n;
int main()
{
int a,b;
int sum=;
scanf("%d",&n);
for(int i=;i<n;i++){
scanf("%d%d",&a,&b);
s[i]=a;
f[i]=b;
}
//memset(dp,0,sizeof(dp)); //不能为0值。。。因为f[i]有小于0的值,应该取负无穷大的值
for(int i=;i<V*+;i++)
dp[i]=-INF;
dp[V]=;
for(int i=;i<n;i++){
if(s[i]>=){
for(int v=V*;v>=s[i];v--){ //倒叙
dp[v]=max(dp[v],dp[v-s[i]]+f[i]);
}
}
else{
for(int v=;v<=V*;v++){ //正序
dp[v]=max(dp[v],dp[v-s[i]]+f[i]);
}
}
}
for(int i=;i<=V*;i++){
if(i-+dp[i]>sum && dp[i]>=){
sum=i-+dp[i];
}
}
printf("%d\n",sum);
return ;
}

POJ 2184 Cow Exhibition (01背包的变形)的更多相关文章

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

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

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

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

  3. POJ 2184 Cow Exhibition 01背包

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

  4. poj 2184 Cow Exhibition(背包变形)

    这道题目和抢银行那个题目有点儿像,同样涉及到包和物品的转换. 我们将奶牛的两种属性中的一种当作价值,另一种当作花费.把总的价值当作包.然后对于每一头奶牛进行一次01背包的筛选操作就行了. 需要特别注意 ...

  5. PKU 2184 Cow Exhibition 01背包

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

  6. POJ 2184 Cow Exhibition(背包)

    希望Total Smart和Totol Funess都尽量大,两者之间的关系是鱼和熊掌.这种矛盾和背包的容量和价值相似. dp[第i只牛][j = 当前TotS] = 最大的TotF. dp[i][j ...

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

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

  8. poj 2184 Cow Exhibition(dp之01背包变形)

    Description "Fat and docile, big and dumb, they look so stupid, they aren't much fun..." - ...

  9. poj 2184 Cow Exhibition(01背包)

    Cow Exhibition Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10882   Accepted: 4309 D ...

随机推荐

  1. DropDownList另一种写法

    2013-09-29 17:04:47 1.性别: <asp:DropDownList ID="DrpSex" runat ="server"  Widt ...

  2. 【风马一族_Android】让app上传到Android市场的网站介绍

    豌豆荚  开发者中心 http://open.wandoujia.com/account/info China app http://www.chinaapp.org

  3. Azure + vsftpd + ubntu14 + 虚拟用户 遇到的问题:从网上摘抄

    :在Azure安装好ubuntu虚拟机,安装包选择ubuntu14.04 LTS,选择LTS,以便微软对其以后的更好支持,不选就可能技术支持不会很久,现只开一台,端口默认选择22 :打开虚拟机,进入端 ...

  4. hadoop2.2.0伪分布式搭建

    1.准备Linux环境     1.0点击VMware快捷方式,右键打开文件所在位置 -> 双击vmnetcfg.exe -> VMnet1 host-only ->修改subnet ...

  5. silverlight将字符串转化为控件

    silverlight的System.Windows.Markup命名空间下,提供了XamlReader.Load()方法可以将字符串转换为控件. 代码 StringBuilder sbGrid = ...

  6. Berkeley DB分布式探索

    明天回家就没有网络,今晚就将整个编写过程记录下来.顺带整理思路以解决未能解决的问题. 标题有点托大,想将Berkeley DB做成分布式存储,感觉很高端的样子,实际上就是通过ssh将Berkeley ...

  7. hibernate 知识梳理

    一.hibernate背景介绍: 作者: Gavin King 分hibernate ORM(for relation db),OGM(for nosql db),hearch,validator,t ...

  8. 一款非常炫酷的jQuery动态随机背景滚动特效

    一款非常炫酷的jQuery动态随机背景滚动特效 图片背景会不停息的滚动,带有那种漂浮的视觉效果,小圈圈飘动. 更好的是还兼容IE6浏览器,大伙可以好好研究研究. 适用浏览器:IE6.IE7.IE8.3 ...

  9. 通过获取客户端Json数据字符串,反序列化为实体对象的一段代码

    #region 保存候选人数据 /// <summary> /// 保存候选人数据 /// </summary> /// <param name="entity ...

  10. URL地址下载图片到本地

    package test.dao; import eh.base.dao.DoctorDAO; import eh.entity.base.Doctor; import junit.framework ...