首先,什么叫多重背包呢?

大概意思就是:一个背包有V总容量,有N种物品,其价值分别为Val1,Val2……,Val3,体积对应的是Vol1,Vol2,……,Vol3,件数对应Num1,Num2……,Num3

求背包至多装满的最大总价值。

其实,首先可以当作01背包来做,这时候复杂度就是O(V*sum(Num[i]));

简单代码来说就是

  for(int i=1;i<=N;i++)
for(int j=1;j<=Num[i];j++)
for(int k=V;k>=Vol[i];k++)
dp[k]=max(dp[k],dp[k-Vol[i]]+Val[i]);

很容易超时。如果M大的话。从大神的背包九讲看到一个化成O(Vsum(log(Num[i])))

大概意思就是利用先判断是否为完全背包情况,否则二进制压缩进行01背包的步骤。任何一个数目Num[i],可以表示为1+2^1 +……+2^p+Num[i]-2^(p+1)+1 其中确定p的条件是Num[i]-2^(p+1)+1>0,Num[i]-2^(p+2)+1<0

这样我们就可以将第i件物品化成 logNum[i]件物品,起对应的容量和价值,分别对应相应倍数

简单代码就是

     int i,j,k;
for(i=1; i<=N; i++)
if(Vol[i]*Num[i]>=V) //n*v>=V 完全背包
{
for(j=Vol[i]; j<=V; j++) //从val到V
{
dp[j]=max(dp[j],dp[j-Vol[i]]+Val[i]);
} }
else
{
k=1;
int num_tmp=Num[i]; //取出数目
while(k<num_tmp) //二进制优化
{
for(j=V; j>=k*Vol[i]; j--) //k*Vol ,k*Val的背包
dp[j]=max(dp[j],dp[j-k*Vol[i]]+Val[i]);
num_tmp-=k;
k<<=1;
}
for(j=V; j>=num_tmp*vol[i]; j--) //num_tmp*Vol[i],num_tmp*Val[i]背包问题
{
dp[j]=max(dp[j],dp[j-num_tmp*Vol[i] ]+Val[i]);
} }

之后对于HDU1171,2194,用第一种算法就轻松通过了。

HDU1171的题目要我们做的就是将总和/2规划成资产“不会大”的学院当成容量背包。

代码

#include<stdio.h>
#include<string.h>
int dp[250000];
int val[52];
int num[52];
int main(){ int n,i,j,k;
int sum,V;
while(scanf("%d",&n)&&n>0){ memset(dp,0,sizeof(dp)); sum=0;
for(i=1;i<=n;i++){
scanf("%d%d",&val[i],&num[i]);
sum+=val[i]*num[i];
}
V=sum/2; //B的
for(i=1;i<=n;i++){
for(j=1;j<=num[i];j++){
for(k=V;k>=val[i];k--){
dp[k]=dp[k]>dp[k-val[i]]+val[i]?dp[k]:dp[k-val[i]]+val[i]; } } }
printf("%d %d\n",sum-dp[V],dp[V]); } return 0; }

而HDU2191则是赤裸裸的套上模版,更是轻松过。不过在取数组名字时候真是乱七八糟。我有时候用cost val num,有时候用vol val num不过关系都不大。

#include<stdio.h>
#include<string.h>
int dp[106];
int cst[100];
int val[100];
int num[100];
int max(int a,int b){
return a>b?a:b; }
int main(){ int cases,V,N,i,j,k;
scanf("%d",&cases);
while(cases--){
scanf("%d%d",&V,&N);
memset(dp,0,sizeof(dp));
memset(cst,0,sizeof(cst));
memset(val,0,sizeof(val));
memset(num,0,sizeof(num));
for(i=1;i<=N;i++)
scanf("%d%d%d",&cst[i],&val[i],&num[i]); for(i=1;i<=N;i++)
for(j=1;j<=num[i];j++)
for(k=V;k>=cst[i];k--){
dp[k]=max(dp[k],dp[k-cst[i]]+val[i]); } printf("%d\n",dp[V]); }
return 0; }

对于HDU2844这题目,我错了很多次……大多数都是RE……后来大我AC了我才发现,是我当初的数组开的太小了。

大概思路就是:令vol=val,来做成背包,能付多少钱嘛,那么dp[i]==i就是刚好付i元,最后统计一下就好啦。

一开始我试着直接化成01背包,果断TLE了……

/*******************************************************************************/
/* OS : 3.2.0-58-generic #88-Ubuntu SMP Tue Dec 3 UTC 2013 GNU/Linux
* Compiler : GCC 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
* Encoding : UTF8
* Date : 2014-03-11
* All Rights Reserved by yaolong.
*****************************************************************************/
/* Description: ***************************************************************
*****************************************************************************/
/* Analysis: ******************************************************************
*****************************************************************************/
/*****************************************************************************/ #include<stdio.h>
#include<string.h>
int dp[100002];
int val[122];
int num[122];
int max(int a,int b)
{
return a>b?a:b; }
int main()
{ int V,N,i,j,res; while(~scanf("%d%d",&N,&V)&&(N||V))
{ memset(dp,0,sizeof(dp)); for(i=1; i<=N; i++)
scanf("%d",&val[i]);
for(i=1; i<=N; i++)
scanf("%d",&num[i]); for(i=1; i<=N; i++)
{
if(val[i]*num[i]>=V) //n*v>=V 完全背包
{
for(j=val[i]; j<=V; j++) //从val到V
{
dp[j]=max(dp[j],dp[j-val[i]]+val[i]);
} }
else
{
int k=1;
int num_tmp=num[i]; //取出数目
while(k<num_tmp) //二进制优化
{
for(j=V; j>=k*val[i]; j--) //k*val ,k*val的背包
dp[j]=max(dp[j],dp[j-k*val[i]]+k*val[i]);
num_tmp-=k;
k<<=1;
}
for(j=V; j>=num_tmp*val[i]; j--) //num_tmp*val[i],num_tmp*val[i]背包问题
{
dp[j]=max(dp[j],dp[j-num_tmp*val[i]]+num_tmp*val[i]);
} } } res=0; for(i = 1; i<=V; i++) if(dp[i]==i)
{
res++;
} printf("%d\n",res); } return 0; }

后来我又写了一遍,因为我当初把各种背包函数写在外面出错了,其实我一直不明白为什么GCC提交,打注释就有问题……

/*******************************************************************************/
/* OS : 3.2.0-58-generic #88-Ubuntu SMP Tue Dec 3 UTC 2013 GNU/Linux
* Compiler : GCC 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
* Encoding : UTF8
* Date : 2014-03-11
* All Rights Reserved by yaolong.
*****************************************************************************/
/* Description: ***************************************************************
*****************************************************************************/
/* Analysis: ******************************************************************
*****************************************************************************/
/*****************************************************************************/ #include<stdio.h>
#include<string.h>
int dp[100002];
int w[122]; //weight
int n[122]; //num
int v[122]; //volume
int V,N;//Volume of the Pack,Number of things int max(int a,int b)
{
return a>b?a:b; }
void ZeroOnePack(int vol,int weight){
int i;
for(i=V;i>=vol;i--){
dp[i]=max(dp[i],dp[i-vol]+weight);
} }
void CompletePack(int vol,int weight){
int i;
for(i=vol;i<=V;i++){
dp[i]=max(dp[i],dp[i-vol]+weight);
} }
void MultiPack(int vol,int weight,int num){ if(num*vol>=V){//CompletePack
CompletePack(vol,weight);
return ;
}
int k=1;
while(k<num){
ZeroOnePack(k*vol,k*weight); //ZeroOnePackage
num-=k;
k<<=1;
}
ZeroOnePack(num*vol,num*weight); }
int main()
{
int i,res;
while(scanf("%d%d",&N,&V),N+V){
memset(dp,0,sizeof(dp));
for(i=1;i<=N;i++)
scanf("%d",&w[i]);
for(i=1;i<=N;i++)
scanf("%d",&n[i]);
for(i=1;i<=N;i++)
MultiPack(w[i],w[i],n[i]); res=0;
for(i=1;i<=V;i++)
if(dp[i]==i){
res++;
}
printf("%d\n",res); } return 0; }

多重背包的入门题目HDU1171,2191,2844.的更多相关文章

  1. POJ 1014 Dividing(多重背包)

    Dividing   Description Marsha and Bill own a collection of marbles. They want to split the collectio ...

  2. hdu 2191 珍惜现在,感恩生活 多重背包入门题

    背包九讲下载CSDN 背包九讲内容 多重背包: hdu 2191 珍惜现在,感恩生活 多重背包入门题 使用将多重背包转化为完全背包与01背包求解: 对于w*num>= V这时就是完全背包,完全背 ...

  3. hdu 2844 Coins (多重背包)

    题意是给你几个数,再给你这几个数的可以用的个数,然后随机找几个数来累加, 让我算可以累加得到的数的种数! 解题思路:先将背包初始化为-1,再用多重背包计算,最后检索,若bb[i]==i,则说明i这个数 ...

  4. Coins(HDU 2844):一个会超时的多重背包

    Coins  HDU 2844 不能用最基础的多重背包模板:会超时的!!! 之后看了二进制优化了的多重背包. 就是把多重转变成01背包: 具体思路见:http://www.cnblogs.com/tt ...

  5. hdu 2191 多重背包 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活

    http://acm.hdu.edu.cn/showproblem.php?pid=2191 New~ 欢迎“热爱编程”的高考少年——报考杭州电子科技大学计算机学院关于2015年杭电ACM暑期集训队的 ...

  6. [原]hdu2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 (这个只是题目名字) (多重背包)

    本文出自:http://blog.csdn.net/svitter 原题:http://acm.hdu.edu.cn/showproblem.php?pid=2191 题意:多重背包问题.转换成为01 ...

  7. HDU 2844 Coins(多重背包)

    点我看题目 题意 :Whuacmers有n种硬币,分别是面值为A1,A2,.....,An,每一种面值的硬币的数量分别是C1,C2,......,Cn,Whuacmers想买钱包,但是想给人家刚好的钱 ...

  8. HDu -2844 Coins多重背包

    这道题是典型的多重背包的题目,也是最基础的多重背包的题目 题目大意:给定n和m, 其中n为有多少中钱币, m为背包的容量,让你求出在1 - m 之间有多少种价钱的组合,由于这道题价值和重量相等,所以就 ...

  9. hdu 2191多重背包

    悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Jav ...

随机推荐

  1. Ubuntu的which、whereis、locate和find命令

    which 只能寻找执行文件 ,并在PATH变量里面寻找. whereis 从linux文件数据库(/var/lib/slocate/slocate.db)寻找,所以有可能找到刚刚删除,或者没有发现新 ...

  2. windows下mysql 控制台操作

    windows mysql 控制台操作 1.首先打开cmd进入dos窗口 2.切换至目录: F: cd PHPnow-1.5.6\MySQL-5.0.90\bin 3.进入mysql: mysql - ...

  3. PHP技术开发微信公众平台

    这篇文章主要介绍了微信公众平台的两种模式(编辑模式和开发模式)顾名思义编辑模式就是写普通的功能,开发模式具有更多的功能,下面主要是针对开发模式做介绍,需要的朋友可以参考下 下面通过图文并茂的方式介绍微 ...

  4. 一个免费的自动化跨平台测试JavaScript的工具——BrowserSwarm

    BrowserSwarm是一个免费工具,能够自动化跨平台测试JavaScript.

  5. Java多线程编程的常见陷阱(转)

    Java多线程编程的常见陷阱 2009-06-16 13:48 killme2008 blogjava 字号:T | T 本文介绍了Java多线程编程中的常见陷阱,如在构造函数中启动线程,不完全的同步 ...

  6. servletConfig对象

    在Servlet的配置文件中,可以使用一个或多个<init-param>标签为servlet配置一些初始化参数. 当servlet配置了初始化参数后,web容器在创建servlet实例对象 ...

  7. Android 系统名字、版本、API level的对应关系

    从官网上找到的,具体地址是: http://source.android.com/source/build-numbers.html Code name Version API level Lolli ...

  8. BA - 读书雷达10本必读书

    https://www.douban.com/doulist/43172796/ 用户故事与敏捷方法 入门篇之一: “是每个ThoughtWorks BA都读的经典入门书籍,详细介绍了用户故事及实用操 ...

  9. 12种超酷HTML5 SVG和CSS3浮动标签效果

    这是一组效果很炫酷的SVG和CSS3表单浮动标签特效.这组浮动标签特效共12种效果,这些浮动标签效果部分在元素的伪元素上使用CSS transitions和CSS animations完毕,一部分则使 ...

  10. 支持“***Context”上下文的模型已在数据库创建后发生更改。请考虑使用 Code First 迁移更新数据库(http://go.microsoft.com/fwlink/?LinkId=238269)。

    在用VS进行MVC开发的过程中遇到如下问题: 支持“***Context”上下文的模型已在数据库创建后发生更改.请考虑使用 Code First 迁移更新数据库(http://go.microsoft ...