POJ 1742 Coins(多重背包,优化)
《挑战程序设计竞赛》上DP的一道习题。
很裸的多重背包。下面对比一下方法,倍增,优化定义,单调队列。
一开始我写的倍增,把C[i]分解成小于C[i]的2^x和一个余数r。
dp[i][j]的定义前i个数字能否到凑出j来,改成一位滚动数组。
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<queue>
#include<vector>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
//#include<bits/stdc++.h>
using namespace std; #define PS push
#define PB push_back
#define MP make_pair
#define fi first
#define se second const int maxm = 1e5+;
const int maxn = ; bool dp[maxm]; int A[maxn], C[maxn]; int n, m; inline int read()
{
int ret; char c; while(c = getchar(),c<''||c>'');
ret = c-'';
while(c = getchar(),c>=''&&c<='') ret = ret* + c-'';
return ret;
} //#define LOCAL
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
dp[] = true;
while(scanf("%d%d",&n,&m),n+m){
for(int i = ; i < n; i++)
A[i] = read();
for(int i = ; i < n; i++){
C[i] = read();
}
memset(dp+,,sizeof(bool)*m);
for(int i = ; i < n; i++){
int b = ,vol = A[i];
while((<<b)<=C[i]+){ //11...111 (b) <= C[i] -> 100.... <= C[i]+1
for(int S = m; S >= vol; S--){
dp[S] = dp[S-vol]||dp[S];
}
b++; vol<<=;
}
int r = C[i]-(<<(b-))+;
if(r){
int Vol = A[i]*r;
for(int S = m; S >= Vol; S--){
dp[S] = dp[S-Vol]||dp[S];
}
}
}
int ans = ;
for(int i = ; i <= m; i++) ans += dp[i];
printf("%d\n",ans);
}
return ;
}
binary
复杂度是O(n*m*sigma(logC[i]))。然后果断就TLE了。
再优化只有单调队列了,扎扎并没有想到怎么用单调队列。
书上的解法是优化定义,同样的时间复杂度记录bool信息太浪费了。
dp[i][j]表示前i种凑出面值j时第i种硬币最多的剩余。
核心代码:
int ans = ;
memset(dp+,-,sizeof(int)*m);
for(int i = ; i < n; i++){
for(int j = ; j <= m; j++){
if(~dp[j]) dp[j] = C[i]; //之前凑出了j
else if(j >= A[i] && dp[j-A[i]]>) { //还可以在凑
dp[j] = dp[j-A[i]] - ;
ans++;
}else dp[j] = -; //凑不出
}
}
跑了1985ms。
另外还发现一件有意思的事情,
当我用一个临时变量数组cnt[j]记录凑出j的最小次数的时候,跑了1235ms。(系统分配似乎更快一点?
int ans = ;
memset(dp+,,sizeof(bool)*m);
for(int i = ; i < n; i++){
int cnt[maxm] = {};
for(int j = A[i]; j <= m; j++){
if(!dp[j] && dp[j-A[i]] && cnt[j-A[i]] < C[i]){
cnt[j] = cnt[j-A[i]] + ;
ans++;
dp[j] = true;
}
}
}
参考了http://www.cnblogs.com/xinsheng/archive/2013/12/04/3458362.html之后,明白了单调队列的做法的。
总体来说是划分同余类,对于一个同余类用单调队列维护滑动窗口的最小值。(左端为最多减去C[i]个物品的的状态
这道题只要判断存在性,连单调性都用不上(insert不需要删除队尾元素),只要维护滑动窗口的和以及大小就可以了。
但是这道题数据丧心病狂,直接分组常数比较大TLE了。我改成判断0-1和完全才2891 ms飘过(常数写丑了
int ans = ;
memset(dp+,,sizeof(bool)*m);
for(int i = ; i < n; i++){
if(C[i] == ){
for(int j = m; j >= A[i]; j--){
dp[j] = dp[j-A[i]] || dp[j];
}
}
else if(A[i]*C[i] >= m){
for(int j = A[i]; j <= m; j++){
dp[j] = dp[j-A[i]] || dp[j];
}
}
else {
for(int r = ; r < A[i]; r++){
int sum = , hd = , rr = ;
for(int j = r; j <= m; j += A[i]){
if(rr - hd > C[i]){
sum -= q[hd++];
}
sum += q[rr++] = dp[j];
if(sum) dp[j] = true;
}
}
}
}
for(int i = ; i <= m; i++) ans += dp[i];
似乎完全的情况比较多的情况,我只改了一个语句的不同结果。。
dp[j] = dp[j-A[i]] || dp[j]; 2891 ms
if(dp[j-A[i]]) dp[j] = true; 2813 ms
if(dp[j-A[i]] && !dp[j]) dp[j] = true; 2110 ms
POJ 1742 Coins(多重背包,优化)的更多相关文章
- POJ 1742 Coins(多重背包, 单调队列)
Description People in Silverland use coins.They have coins of value A1,A2,A3...An Silverland dollar. ...
- POJ 1742 Coins (多重背包)
Coins Time Limit: 3000MS Memory Limit: 30000K Total Submissions: 28448 Accepted: 9645 Descriptio ...
- poj 1742 coins_多重背包
题意:给你N个种硬币,价值和数量,知道手表不大于m,问能组成(1~m)的价格有多少种情况 套套上次那题的模板直接就行了,http://blog.csdn.net/neng18/article/deta ...
- POJ 3260 The Fewest Coins(多重背包+全然背包)
POJ 3260 The Fewest Coins(多重背包+全然背包) http://poj.org/problem?id=3260 题意: John要去买价值为m的商品. 如今的货币系统有n种货币 ...
- hdu 2844 poj 1742 Coins
hdu 2844 poj 1742 Coins 题目相同,但是时限不同,原本上面的多重背包我初始化为0,f[0] = 1;用位或进行优化,f[i]=1表示可以兑成i,0表示不能. 在poj上运行时间正 ...
- poj 1742 Coins(二进制拆分+bitset优化多重背包)
\(Coins\) \(solution:\) 这道题很短,开门见山,很明显的告诉了读者这是一道多重背包.但是这道题的数据范围很不友好,它不允许我们直接将这一题当做01背包去做.于是我们得想一想优化. ...
- poj 1742 Coins(二进制优化多重背包)
传送门 解题思路 多重背包,二进制优化.就是把每个物品拆分成一堆连续的\(2\)的幂加起来的形式,然后把最后剩下的也当成一个元素.直接类似\(0/1\)背包的跑就行了,时间复杂度\(O(nmlogc) ...
- poj 1742 Coins (多重背包)
http://poj.org/problem?id=1742 n个硬币,面值分别是A1...An,对应的数量分别是C1....Cn.用这些硬币组合起来能得到多少种面值不超过m的方案. 多重背包,不过这 ...
- Poj 1742 Coins(多重背包)
一.Description People in Silverland use coins.They have coins of value A1,A2,A3...An Silverland dolla ...
随机推荐
- [CentOS7] Segmentation fault (core dumped),但是在主机上找不到core文件
1.问题描述 程序执行报:Segmentation fault (core dumped),但是在主机上找不到core文件 2.如何让系统生成core file /home>ulimit -ac ...
- 51nod1042(0-x出现次数&分治)
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1042 题意:中文题诶- 思路:这道题和前面的51nod100 ...
- 2017-10-23 NOIP模拟赛
叉叉 题目描述 现在有一个字符串,每个字母出现的次数均为偶数.接下来我们把第一次出现的字母a和第二次出现的a连一条线,第三次出现的和四次出现的字母a连一条线,第五次出现的和六次出现的字母a连一条线.. ...
- 2017-10-20 NOIP模拟赛2
P98 a [问题描述]你是能看到第一题的 friends 呢.——hja世界上没有什么比卖的这么贵的弹丸三还令人绝望的事了,所以便有了这么一道题.定义?(?)为满足(? × ?)|?的有序正整数对( ...
- Android OpenGLES2.0(十七)——球形天空盒VR效果实现
在3D游戏中通常都会用到天空盒,在3D引擎中也一般会存在天空盒组件,让开发者可以直接使用.那么天空盒是什么?天空盒又是如何实现的呢?本篇博客主要介绍如何在Android中利用OpenGLES绘制一个天 ...
- 消息队列RabbitMQ、缓存数据库Redis
1.RabbitMQ消息队列 1.1 RabbitMQ简介 AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中 ...
- dblink 简单使用
create extension dblink查看连接:select dblink_get_connections()断开所有连接:select dblink_disconnect()断开指定名称的连 ...
- python 3.7 生成数据库文档
开发阶段数据库总是有变动,开发人员需要维护文档给相关人员使用,故编写一个脚本自动生成数据库文档 生成的excel如下 import cx_Oracle import os from openpyxl ...
- bitnami-redmine Apache服务启动不起来
方法一: 通过 netstat -a -o 查看端口占用情况,关闭调用相关端口的进程. c:\> netstat -a -o Active Connections Proto Local ...
- 《从0到1学习Flink》—— Flink 项目如何运行?
前言 之前写了不少 Flink 文章了,也有不少 demo,但是文章写的时候都是在本地直接运行 Main 类的 main 方法,其实 Flink 是支持在 UI 上上传 Flink Job 的 jar ...