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 ...
随机推荐
- jQuery点击弹出层,弹出模态框,点击模态框消失
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...
- Hadoop3.0 DataNode启动不成功——java.net.BindException: Port in use: localhost:0 Caused by: java.net.BindException: Cannot assign requested address解决办法
一.问题出现的原因 启动Hadoop分布式环境时出现主节点的namenode.secondarynamenode启动成功,但是Worker节点datenode启动不成功. hadoop@master$ ...
- shell学习(13)- vim
其中部分内容是转载的. 在命令状态下对当前行用== (连按=两次), 或对多行用n==(n是自然数)表示自动缩进从当前行起的下面n行.你可以试试把代码缩进任意打乱再用n==排版,相当于一般IDE里的c ...
- js index of()用法
含义: indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置.(工作中常用) 提示和注释: 注释:indexOf() 方法对大小写敏感! 注释:如果要检索的字符串值没有出现,则该方 ...
- 华东交通大学2017年ACM“双基”程序设计竞赛 1002
Problem Description 一天YZW参加了学校组织交际舞活动,活动的开始活动方分别给男生和女生从1-n进行编号,按照从小到大顺时针的方式进行男女搭档分配,相同编号的男女组合成一对,例如一 ...
- JD孔_20160912
1.买的 “航嘉(Huntkey)大白803 8位3米 总控开关 防过载保护 插座/排插/拖” http://item.jd.com/1786149.html#product-detail 2.
- AJAX下拉框联动
function getProvince() { var ProName = $("#dvProv").val(); LoadProvince(ProName); } functi ...
- cgkib动态代理详解-不依赖接口,速度快
1. cglib原理-不依赖接口,速度快 使用ASM字节框架动态生成要代理类的子类,子类重写final以外的方法,织入横切逻辑 2. 示例-实现MethodInterceptor Test.java ...
- java环境安装(win7)
首先,你应该已经安装了 java 的 JDK 了,笔者安装的是:jdk-7u13-windows-x64 接下来主要讲怎么配置 java 的环境变量,也是为了以后哪天自己忘记了做个备份 1.进入&qu ...
- 解惑好文:移动端H5页面高清多屏适配方案
背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉MM会给我们一个psd文件,称之为视觉稿. 对于移动端开发而言,为了做到页面高清的效果,视觉稿的规范 ...