多重背包(MultPack = ZeroOnePack + CompletePack)
HiHoCoder_offer6_04
题目4 : 奖券兑换
描述
小Hi在游乐园中获得了M张奖券,这些奖券可以用来兑换奖品。
可供兑换的奖品一共有N件。第i件奖品需要Wi张奖券才能兑换到,其价值是Pi。
小Hi使用不超过M张奖券所能兑换到的最大奖品总价值是多少?
输入
第一行两个整数N,M。
接下来N行,每行两个整数Wi,Pi。
对于 50%的数据: 1≤N,M≤1000
对于 100%的数据: 1≤N,M≤105,1≤Pi,Wi≤10。
输出
一行一个整数,表示最大的价值。
- 样例输入
-
3 10
2 3
8 8
10 10 - 样例输出
-
11
明显是一个01背包问题,背了一下结果:过了一半的数据,剩下的TLE了。 仔细观察数据, 1 <= n , m <= 100000, 1 <= wi , pi <= 10。明显每个物品的价值和容量都非常小,也就是说不同容量不同不价值的物品最多有:10 * 10 = 100种。
既然这个数据项这么小,那么它就是这个问题的突破口。对于每一个物品,已知它的num(数量 )和 weight(重量) & value(价值),刚好可以使用多重背包。加上二进制优化,复杂度O(10 * 10 * log 100000);
代码:
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
int num[][];
int dp[]; void CompletePack(int weight, int value, int totWeight)
{
for(int w = weight; w <= totWeight; w ++){
dp[w] = max(dp[w], dp[w - weight] + value);
}
} void zeroOnePack(int weight, int value, int totWeight)
{
for(int w = totWeight; w >= weight; w --){
dp[w] = max(dp[w], dp[w - weight] + value);
}
} void multiPack(int weight, int value, int totWeight)
{
if(weight * num[weight][value] > totWeight){
CompletePack(weight, value, totWeight);
}else{
int k = , tmpNum = num[weight][value];
while(k < tmpNum){
zeroOnePack(k * weight, k * value, totWeight);
tmpNum -= k;
k <<= ;
}
zeroOnePack(tmpNum * weight, tmpNum * value, totWeight);
}
} int main()
{
int n,m,weight,value;
cin>>n>>m;
for(int i = ; i < n; i ++){
scanf("%d%d",&weight, &value);
num[weight][value] ++;
}
for(int i = ; i <= ; i ++){
for(int j = ; j <= ; j ++){
multiPack(i, j, m);
}
}
printf("%d\n",dp[m]);
return ;
}
————————++++++————————
多重背包(MultPack = ZeroOnePack + CompletePack)的更多相关文章
- HDU-2844 Coins(多重背包)
Problem Description Whuacmers use coins.They have coins of value A1,A2,A3...An Silverland dollar. On ...
- hdu 2191 多重背包 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
http://acm.hdu.edu.cn/showproblem.php?pid=2191 New~ 欢迎“热爱编程”的高考少年——报考杭州电子科技大学计算机学院关于2015年杭电ACM暑期集训队的 ...
- DP大作战——多重背包
题目描述 在之前的上机中,零崎已经出过了01背包和完全背包,也介绍了使用-1初始化容量限定背包必须装满这种小技巧,接下来的背包问题相对有些难度,可以说是01背包和完全背包的进阶问题. 多重背包:物品可 ...
- poj 2392 多重背包
题意:有几个砖,给出高度,能放的最大高度和数目,求这些砖能垒成的最大高度 依据lim排个序,按一层一层进行背包 #include<cstdio> #include<iostream& ...
- poj 1276 多重背包
735 3 4 125 6 5 3 350 //735的最大额,3种,4个125,6个5,3个350 633 4 500 30 6 100 1 5 0 1 735 0 0 3 10 100 10 50 ...
- hdu 1059 多重背包
题意:价值分别为1,2,3,4,5,6的物品个数分别为a[1],a[2],a[3],a[4],a[5],a[6],问能不能分成两堆价值相等的. 解法:转化成多重背包 #include<stdio ...
- poj1276 多重背包
//Accepted 1100 KB 47 ms //多重背包 #include <cstdio> #include <cstring> #include <iostre ...
- poj2392 多重背包
//Accepted 868 KB 188 ms //多重背包 #include <cstdio> #include <cstring> #include <iostre ...
- poj1014 dp 多重背包
//Accepted 624 KB 16 ms //dp 背包 多重背包 #include <cstdio> #include <cstring> #include <i ...
随机推荐
- Multisim破解教程
转载:http://www.121down.com/article/article_52879.html
- 洛谷 4251 [SCOI2015]小凸玩矩阵
[题解] 二分答案+二分图匹配. 先二分最小值Min,然后扫一遍这个矩阵,把满足a[i][j]<=Min的i,j连边,之后跑二分图匹配,如果最大匹配数大于等于n-k+1,当前的Min即是合法的. ...
- 中文情感分析 glove+LSTM
最近尝试了一下中文的情感分析. 主要使用了Glove和LSTM.语料数据集采用的是中文酒店评价语料 1.首先是训练Glove,获得词向量(这里是用的300d).这一步使用的是jieba分词和中文维基. ...
- [bzoj3131]淘金[sdoi2013][数位DP]
求出每个数i可以被转移到的数目$f[i]$,则点$(i,j)$中的金子数目为$f[i]*f[j]$,我们就可以用优先队列求解前$k$大. 首先所有的积数目在$10^4$左右,可以先Dfs搜索出所有的数 ...
- 总结for循环及for循环增强遍历数组,list,set和map
一.对于集合 (1)普通for循环 int[] arr = { 2, 1, 2 }; for(int i=0;i<arr.length;i++){ System.out.println(arr[ ...
- 混合图(dizzy.pas/cpp/c)
混合图(dizzy.pas/cpp/c) [题目描述] Hzwer神犇最近又征服了一个国家,然后接下来却也遇见了一个难题. Hzwer的国家有n个点,m条边,而作为国王,他十分喜欢游览自己的国家.他一 ...
- one troubleshooting case about em access issue
Today when trying to open my Oracle EM url, I can not open it. So I thought may be the network is ha ...
- OC-内存管理的一些要点
创建一个BOOK对象,对其属性进行声明 定义. @property 属性声明 定义了对属性的赋值 -(void) dealloc 方法在对象销毁的时候进行调用. #import <Foundat ...
- jquery-mobile 学习笔记之二(表单创建)
绪上 一.注意事项 1. <form> 元素必须设置 method 和 action 属性 2. 每一个表单元素必须设置唯一的 "id" 属性. 该 id 在网站的页面 ...
- Live555研究之中的一个 源码编译
Live555研究之中的一个 源代码编译 Live555 是一个为流媒体提供解决方式的跨平台的C++开源项目,它 ...