(点击此处查看原题)

题意分析

给你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 (单调队列优化多重背包+混合背包)的更多相关文章

  1. [Bzoj4182]Shopping(点分治)(树上背包)(单调队列优化多重背包)

    4182: Shopping Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 374  Solved: 130[Submit][Status][Disc ...

  2. bzoj4182 Shopping 点分治+单调队列优化多重背包

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4182 题解 有一个很直观的想法是设 \(dp[x][i]\) 表示在以 \(x\) 为根的子树 ...

  3. POJ - 1821 单调队列优化DP + 部分笔记

    题意:n个墙壁m个粉刷匠,每个墙壁至多能被刷一次,每个粉刷匠要么不刷,要么就粉刷包含第Si块的长度不超过Li的连续墙壁(中间可不刷),每一块被刷的墙壁都可获得Pi的利润,求最大利润 避免重复粉刷: 首 ...

  4. POJ 2373 单调队列优化DP

    题意: 思路: f[i] = min(f[j]) + 1; 2 * a <= i - j <= 2 *b: i表示当前在第i个点.f[i]表示当前最少的线段个数 先是N^2的朴素DP(果断 ...

  5. POJ 1276 Cash Machine(单调队列优化多重背包)

    Cash Machine Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 38986   Accepted: 14186 De ...

  6. HDU 2191 - 单调队列优化多重背包

    题目: 传送门呀传送门~ Problem Description 急!灾区的食物依然短缺! 为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种 ...

  7. poj 2373 单调队列优化背包

    思路:我们用单调队列保存2*b<=i-j<=2*a中的最大值.那么队列头就是最大值,如果队头的标号小于i-2*b的话,就出队,后面的肯定用不到它了. #include<iostrea ...

  8. poj 3017 单调队列优化动态规划

    思路:dp[i]=min{dp[j]+max(num[j+1]...num[i])},其中sum[i]-sum[j]<=m. 那么我们需要用单调队列维护j到i的最大值. #include< ...

  9. poj 1742 Coins(二进制优化多重背包)

    传送门 解题思路 多重背包,二进制优化.就是把每个物品拆分成一堆连续的\(2\)的幂加起来的形式,然后把最后剩下的也当成一个元素.直接类似\(0/1\)背包的跑就行了,时间复杂度\(O(nmlogc) ...

随机推荐

  1. cesium billboard跨域问题2

    这篇主要是对上一篇博客cesium billboard出现跨域的原理分析 https://www.cnblogs.com/SmilingEye/p/11363837.html 1.源码位置 从Bill ...

  2. kali系统firefox浏览器默认语言改为中文设置方法

    kali中的Firefox浏览器默认为英文,这对英语不够好的我来讲,自然是很麻烦的,下面讲一下如何将语言设置为中文. 1.打开终端,输入 apt -y install firefox-esr-l10n ...

  3. Ubuntu14.04-OpenCV2和3共存相关设置

    文章转自:http://blog.csdn.net/a356337092/article/details/73529635 安装依赖项: sudo apt-get install build-esse ...

  4. MYSQL的两种存储引擎区别

    Innodb引擎 Innodb引擎提供了对数据库ACID事务的支持,并且实现了SQL标准的四种隔离级别.该引擎还提供了行级锁和外键约束,它的设计目标是处理大容量数据库系统,它本身其实就是基于MySQL ...

  5. php-fpm(绕过open_basedir,结合ssrf)

    环境的安装->https://www.cnblogs.com/zaqzzz/p/11870489.html 1.nginx的畸形访问 因为安装的是php7.0,所以需要手动修改一下(版本低的时候 ...

  6. 认识理解Java中native方法(本地方法)

      Java不是完美的,Java的不足除了体现在运行速度上要比传统的C++慢许多之外,Java无法直接访问到操作系统底层(如系统硬件等),为此Java使用native方法来扩展Java程序的功能. 可 ...

  7. mac下的夜神模拟器链接vscode

    1.找到夜神模拟器,点击右键,查看包内容,找到文件夹下面的macos在点击右键打开终端.输入: adb connect 127.0.0.1:62001 dart和flutter交流群:45289287 ...

  8. ubuntu docker 环境安装

    转载:https://www.cnblogs.com/blog-rui/p/9946382.html 1. 在Ubuntu中安装Docker 更新ubuntu的apt源索引 sudo apt-get ...

  9. zip炸弹

    故障系统有人提了zip炸弹的故障,了解了一些关于zip炸弹的常识. 42.zip 是很有名的zip炸弹.一个42KB的文件,解压完其实是个4.5PB的“炸弹”. 更有甚者,一个叫做 droste.zi ...

  10. Apache设置静态文件的失效时间

    步骤1:启用expires模块 [root@zlinux logs]# vim httpd.conf LoadModule expires_module modules/mod_expires.so ...