POJ 1742 (单调队列优化多重背包+混合背包)
题意分析
给你n种不同价值的硬币,价值为val[1],val[2]...val[n],每种价值的硬币有num[1],num[2]...num[n]个,问使用这n种硬币可以凑齐[1,m]内多少价值(换句话说,就是可以恰好支付的价格有多少)
解题思路
一开始觉得这个题也不是很难,就是多重背包问题,但是用二进制优化的多重背包写法TLE后,陷入了深思...
看了数据范围,二进制优化的时间复杂度为O(∑ log(num[i] * V),加上多组输入后....应该是没被冤枉了.....
二进制都不行了,怎么办呢?只能去用单调队列优化多重背包问题了,其时间复杂度为O(n*V),时间刚刚好卡过去...
但是这里又出了一个问题,我用单调队列优化求解仍然得到了TLE?

QAQ,难道还有比单调队列更优的解法?借鉴大佬的题解后,发现这个题目严格意义上算是一个混合背包问题,而用单调队列处理完全背包问题的时候,效率很低,所以将这个题目按照混合背包分别处理后,就可以AC了。
(单调队列优化的讲解可以看看这个,讲的很清晰:http://www.cppblog.com/flyinghearts/archive/2010/09/01/125555.html)
代码区
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<string>
#include<fstream>
#include<vector>
#include<stack>
#include <map>
#include <iomanip> #define bug cout << "**********" << endl
#define show(x, y) cout<<"["<<x<<","<<y<<"] "
#define LOCAL = 1;
using namespace std;
typedef long long ll;
const int inf = 1e9 + ;
const ll mod = 1e9 + ;
const int Max = 1e5 + ; int n, v;
int que[Max], vol[Max], num[Max];
int head, tail;
bool dp[Max]; int main()
{
#ifdef LOCAL
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
while (scanf("%d%d", &n, &v) != EOF && n + v)
{
for (int i = ; i <= n; i++)
scanf("%d", vol + i); //将价值当作体积,无需计算最大价值
for (int j = ; j <= n; j++)
scanf("%d", num + j); memset(dp, false, sizeof(dp));
dp[] = true;
int cnt = ; for (int i = ; i <= n; i++) //题目虽然没明说这个是混合背包,但是单调队列处理01背包和完全背包用时较长,
//故将之用混合背包处理
{
if (num[i] == ) //01背包
{
for (int j = v; j >= vol[i]; j--)
if (dp[j - vol[i]] && !dp[j])
dp[j] = true, cnt++;
continue;
} if (vol[i] * num[i] >= v) //完全背包,这个比较关键,因为用单调队列处理非常耗时
{
for (int j = vol[i]; j <= v; j++)
if (dp[j - vol[i]] && !dp[j])
dp[j] = true, cnt++;
continue;
} for (int res = ; res < vol[i]; res++) //单调队列优化处理
{
head = , tail = -;
int sum = ;
for (int k = res; k <= v; k += vol[i])
{
if (tail - head == num[i])
sum -= que[head++];
que[++tail] = dp[k];
sum += dp[k];
if (sum && !dp[k])
dp[k] = true, cnt++;
}
}
}
printf("%d\n", cnt);
}
return ;
}
POJ 1742 (单调队列优化多重背包+混合背包)的更多相关文章
- [Bzoj4182]Shopping(点分治)(树上背包)(单调队列优化多重背包)
4182: Shopping Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 374 Solved: 130[Submit][Status][Disc ...
- bzoj4182 Shopping 点分治+单调队列优化多重背包
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4182 题解 有一个很直观的想法是设 \(dp[x][i]\) 表示在以 \(x\) 为根的子树 ...
- POJ - 1821 单调队列优化DP + 部分笔记
题意:n个墙壁m个粉刷匠,每个墙壁至多能被刷一次,每个粉刷匠要么不刷,要么就粉刷包含第Si块的长度不超过Li的连续墙壁(中间可不刷),每一块被刷的墙壁都可获得Pi的利润,求最大利润 避免重复粉刷: 首 ...
- POJ 2373 单调队列优化DP
题意: 思路: f[i] = min(f[j]) + 1; 2 * a <= i - j <= 2 *b: i表示当前在第i个点.f[i]表示当前最少的线段个数 先是N^2的朴素DP(果断 ...
- POJ 1276 Cash Machine(单调队列优化多重背包)
Cash Machine Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 38986 Accepted: 14186 De ...
- HDU 2191 - 单调队列优化多重背包
题目: 传送门呀传送门~ Problem Description 急!灾区的食物依然短缺! 为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种 ...
- poj 2373 单调队列优化背包
思路:我们用单调队列保存2*b<=i-j<=2*a中的最大值.那么队列头就是最大值,如果队头的标号小于i-2*b的话,就出队,后面的肯定用不到它了. #include<iostrea ...
- poj 3017 单调队列优化动态规划
思路:dp[i]=min{dp[j]+max(num[j+1]...num[i])},其中sum[i]-sum[j]<=m. 那么我们需要用单调队列维护j到i的最大值. #include< ...
- poj 1742 Coins(二进制优化多重背包)
传送门 解题思路 多重背包,二进制优化.就是把每个物品拆分成一堆连续的\(2\)的幂加起来的形式,然后把最后剩下的也当成一个元素.直接类似\(0/1\)背包的跑就行了,时间复杂度\(O(nmlogc) ...
随机推荐
- luogu2885
P2885 [USACO07NOV]电话线Telephone Wire 给出若干棵树的高度,你可以进行一种操作:把某棵树增高h,花费为h*h. 操作完成后连线,两棵树间花费为高度差*定值c. 求两种花 ...
- Docker实践--搭建Yapi测试平台
背景:项目需要选择不同测试平台,筛选一个最佳平台 现状:一台机器安装多套环境,虚拟机太繁琐 解决方案:通过Docker模拟安装测环境 参考:https://blog.csdn.net/qq_32447 ...
- webpack - 优化阻塞渲染的css
随着浏览器的日新月异,网页的性能和速度越来越好,并且对于用户体验来说也越来越重要. 现在有很多优化页面的办法,比如:静态资源的合并和压缩,code splitting,DNS预读取等等. 本文介绍的是 ...
- flex的圣杯布局记录 (flex : 0 0 80px)
- POI的XWPFTableCell的方法
1. XWPFParagraph addParagraph() 在这个表格单元格中添加一个段落 2. void addParagraph(XWPFParagraph p) 给这个表格加一段 3. ja ...
- uiautomator2 wifi连接手机
[实施方法] 手机和电脑同时连接到同一个wifi上 1.开启远程adb #开启远端adb,这一步需要手机通过USB连接到电脑 adb tcpip 5555 #结果如下:restarting in TC ...
- Windows 7开发:UAC数据重定向 - Win32 Native
Windows 7开发:UAC数据重定向 - Win32 Native 目标 本动手实验中,您将会学习如何: • 故障排除一个文件重定向 问题 • 使用Process Monitor查找引起问题的根本 ...
- springboot整合redis(集群)
一.加入maven依赖 <parent> <groupId>org.springframework.boot</groupId> <artifactId> ...
- cmake log
20:28:54: 为项目RoboticArmProject_CarTerminal_V20190530执行步骤 ...20:28:54: 正在启动 "/usr/bin/make" ...
- RTM of ML.NET
Announcing ML.NET 1.0