(点击此处查看原题)

题意分析

给你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. Linux之信号

    产生信号五种方法: 按键产生:ctrl+c.ctrl+z.ctrl+\ 系统调用产生:如kill.raise.baort 软件条件产生:如定时器alarm 硬件异常产生:非法访问内存(段错误).除0( ...

  2. 【ElasticSearch+NetCore 第二篇】Nest封装

    using Elasticsearch.Net; using Nest; using System; using System.Collections.Generic; using System.Li ...

  3. Protocol Buffers学习笔记

    Protocol Buffers学习笔记 1. 简介 Protocol Buffers是google发明的一种数据交换格式,独立于语言,独立于平台.与其他的数据交换格式有所不同,Protocol Bu ...

  4. SpringBoot保存数据报错:could not execute statement; SQL [n/a]; constraint [PRIMARY];nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement

    使用SpringBoot做JAVA开发时,用Repository.save();保存数据的时候遇到了报错: could not execute statement; SQL [n/a]; constr ...

  5. 黑马vue---31-32、vue过滤器实例

    黑马vue---31-32.vue过滤器实例 一.总结 一句话总结: vue内部的东西,无论是过滤器还是组件,都是键值对的方式 1.过滤器的定义语法? Vue.filter('过滤器的名称', fun ...

  6. [转]Html 页面常用单词

    Html 页面常用单词 本文来自:https://gitee.com/opencc/SchoolAppDemo 第2批: JavaScript ready 准备 function 函数 disappe ...

  7. 详解python中@的用法

    python中@的用法 @是一个装饰器,针对函数,起调用传参的作用. 有修饰和被修饰的区别,‘@function'作为一个装饰器,用来修饰紧跟着的函数(可以是另一个装饰器,也可以是函数定义). 代码1 ...

  8. CISCN 2019 writeup

    划水做了两个pwn和两个逆向...... 二进制题目备份 Re easyGO Go语言,输入有Please字样,ida搜索sequence of bytes搜please的hex值找到字符串变量,交叉 ...

  9. Swift加载Xib创建的Controller

    Xib显示如下: <注意箭头处即可> 按住Control键,点击Files'owner拖动到View即可. 加载该控制器如下: func registerClick() { let reg ...

  10. Nginx+Keepalived高可用负载均衡

    转自 https://www.jianshu.com/p/da26df4f7d60 Keepalived+Nginx实现高可用Web负载均衡 Master backup vip(虚拟IP) 192.1 ...