HDU 3732 Ahui Writes Word(多重背包)
HDU 3732 Ahui Writes Word(多重背包)
http://acm.hdu.edu.cn/showproblem.php?
pid=3732
题意:
初始有N个物品, 每一个物品有cost[i]花费和val[i]价值, 你有m元钱, 如今问你最多能买多少总价值的物品?
当中N<=10W, m<=1W. 且cost[i]和val[i]都在[0,10]范围.
分析:
本题初看直接用01背包来做是直观的想法. 可是考虑到01背包的复杂度为O(N*m), 这么大的复杂度肯定不行.
然后我们发现事实上每种物品仅仅与它的cost[i]和val[i]有关, 假设某两个物品的cost[i]和val[i]全然相等, 我们能够把这两种物品合并(看出一种物品可是数量叠加), 终于我们直接解决一个多重背包问题就可以. 假设是多重背包问题,
复杂度为O(m*sum( log(num[i]) ) ) 当中 num[i]的和为N.
初始我们读取输入, 然后我们把全部的物品排序,然后在分类之后就构成了n种物品, 每种物品具有num[i]个的多重背包问题.
令dp[i][j]==x 表示购买前i种物品时总花费<=j时, 能够获得的最大价值为x.
初始化: dp全为0.
对于第i种商品, 有以下两种情况:
假设val[i]*num[i]>=m, 就做一次全然背包.
假设val[i]*num[i]<m, 就把第i种物品又一次分类, 并做k+1次01背包.
终于所求: dp[n][m]的值.
程序实现, 用的滚动数组逆向递推, 所以dp仅仅有[j]一维.
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=121+5; int n;//合并之后n种物品
int m;//最大花费值
int val[maxn]; //新分类i物品价值
int num[maxn]; //新分类i物品数目
int cost[maxn];//新分类i物品花费
int dp[10000+5]; //1次01背包过程
void ZERO_ONE_PACK(int cost,int val)
{
for(int i=m;i>=cost;i--)
dp[i] = max(dp[i], dp[i-cost]+val);
} //1次全然背包过程
void COMPLETE_PACK(int cost,int val)
{
for(int i=cost;i<=m;i++)
dp[i] = max(dp[i], dp[i-cost]+val);
} //1次多重背包过程
void MULTIPLY_PACK(int cost,int val,int sum)
{
if(cost*sum>=m)
{
COMPLETE_PACK(cost,val);
return ;
} int k=1;
while(k<sum)
{
ZERO_ONE_PACK(cost*k,val*k);
sum-=k;
k*=2;
}
ZERO_ONE_PACK(cost*sum, val*sum);
} //Node用于保存原始输入的每一个单词属性
struct Node
{
int v,c;
bool operator<(const Node &rhs)const
{
return v<rhs.v || (v==rhs.v && c<rhs.c);
}
bool operator==(const Node &rhs)const
{
return v==rhs.v && c==rhs.c;
}
}nodes[100000+5];
int N;//原始N个单词 int main()
{
while(scanf("%d%d",&N,&m)==2)
{
//读取输入
for(int i=1;i<=N;i++)
{
char str[20];
scanf("%s %d%d",str,&nodes[i].v,&nodes[i].c);
} //将原始输入物品合并再分类
sort(nodes+1,nodes+N+1);
n=1;
val[n]=nodes[1].v;
cost[n]=nodes[1].c;
num[n]=1;
for(int i=2;i<=N;i++)
{
if(nodes[i]==nodes[i-1])
num[n]++;
else
{
n++;
val[n]=nodes[i].v;
cost[n]=nodes[i].c;
num[n]=1;
}
} //递推输出
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
MULTIPLY_PACK(cost[i],val[i],num[i]);
printf("%d\n",dp[m]);
}
return 0;
}
HDU 3732 Ahui Writes Word(多重背包)的更多相关文章
- HDU 3732 Ahui Writes Word 多重背包优化01背包
题目大意:有n个单词,m的耐心,每个单词有一定的价值,以及学习这个单词所消耗的耐心,耐心消耗完则,无法学习.问能学到的单词的最大价值为多少. 题目思路:很明显的01背包,但如果按常规的方法解决时间复杂 ...
- hdoj 3732 Ahui Writes Word (多重背包)
之前在做背包的题目时看到了这道题,一看,大喜,这不是裸裸的01背包吗!! 然后华丽丽的超时,相信很多人也和我一样没有考虑到数据量的大小. 时隔多日,回过头来看这道题,依旧毫无头绪....不过相比之前 ...
- hdu 3732 Ahui Writes Word
这是一道背包题,当你题读完了的时候,你会觉得这道题明明就是01背包的完全版吗! no no no no no no no no no no no~~~~~~~~~~~~~~~~~~~~~~~~~~ ...
- 3732 Ahui Writes Word
// N个物品 放进容量为C的背包里面 要求价值最大// 一看 第一反应是0 1背包 不过 N=100000 C=10000// 注意到 v,c在 10以内// 那么 最多就100种组合了 然后就转化 ...
- 【HDOJ】3732 Ahui Writes Word
初看01背包,果断TLE.是因为n和C都比较大.但是vi和ci却很小,转化为多重背包. #include <cstdio> #include <cstring> ][]; ]; ...
- Ahui Writes Word
Ahui Writes Word Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) To ...
- HDU 2082 找单词 (多重背包)
题意:假设有x1个字母A, x2个字母B,..... x26个字母Z,同时假设字母A的价值为1,字母B的价值为2,..... 字母Z的价值为26.那么,对于给定的字母,可以找到多少价值<=50的 ...
- HDU 5445 Food Problem(多重背包+二进制优化)
http://acm.hdu.edu.cn/showproblem.php?pid=5445 题意:现在你要为运动会提供食物,总共需要提供P能量的食物,现在有n种食物,每种食物能提供 t 能量,体积为 ...
- HDU 2844 二进制优化的多重背包
Coins Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
随机推荐
- cookie登录
#coding:utf-8 import tornado.httpserver import tornado.ioloop import tornado.options import tornado. ...
- tcpreplay 缓存算法研究
一. 缓存算法 1.1 算法目的 流量拆分算法的运算会明显影响包的发送速率,为了提高发送速率, tcpreplay 使用了缓存机制,该部分代码也封装在tcpprep工具里,运行 tcpprep ( ...
- [Oracle] oracle统计信息
Oracle统计信息 Oracle数据库里的统计信息可以分为6种类型: 表的统计信息 索引的统计信息 列的统计信息 系统统计信息 数据字典统计信息 内部对象统计信息 图 1: Oracle统计信息 基 ...
- windows 2012(64位) IIS配置asp程序 500 - 内部服务器错误。您查找的资源存在问题,因而无法显示。
在网上找了很久,包括常规的设置父路径之类的,一直都不可以,搞了一晚上毫无成就感,第二天早上无意中看到一篇文章,说到点子上了,非常感谢.源地址已经找不到了,我把大概的问题截图说明一下. 方法如下:1.打 ...
- android的百度地图开发(二) 定位
参考:http://blog.csdn.net/mr_wzc/article/details/51590485 第一步,初始化LocationClient类 //获取地图控件引用 mMapView = ...
- Fiddler抓包7-post请求(json)【转载】
本篇转自博客:上海-悠悠 原文地址:http://www.cnblogs.com/yoyoketang/tag/fiddler/ 前言上一篇讲过get请求的参数都在url里,post的请求相对于get ...
- 出现函数重载错误call of overloaded ‘printfSth(double)’ is ambiguous
class C: { public: void printfSth(int i) { cout<<"C::printfSth(int i):"<<i< ...
- cmake add_executable 与 include_directories
在cmake里add_executable里如果没有包含.cpp文件,该.cpp文件就不适用include_directories包含文件
- 利用ICSharpCode进行压缩和解压缩
说说我利用ICSharpCode进行压缩和解压缩的一些自己的一下实践过程 1:组件下载地址 参考文章:C#使用ICSharpCode.SharpZipLib.dll压缩文件夹和文件 2: 文件类 // ...
- Ubuntu14.04 在右键中添加 在终端中打开
1.在terminal中执行: sudo apt-get install nautilus-open-terminal 此时可能会提示:nable to locate package nautilus ...