POJ 1742 Coins 多重背包单调队列优化

http://poj.org/problem?id=1742

题意:

很多硬币,有价值和数量,给出一个上限,问上限内有多少种钱数可以由这些硬币组成。

分析:

好像是楼教主男人八题之一。然后学多重背包单调队列优化时看了别人的程序。。所以后来写了就1A了=。=

前一篇小小总结了一下多重背包单调队列优化(http://www.cnblogs.com/james47/p/3894772.html),这里就不写了。

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4
 5 int n, m, head, tail;
 6 int a[150], c[150];
 7 int q[(int)1e5+100];
 8 bool dp[(int)1e5+100];
 9 int main()
10 {
11     while(scanf("%d %d", &n, &m) && (n+m))
12     {
13         for (int i = 0; i < n; i++)
14             scanf("%d", a+i);
15         for (int i = 0; i < n; i++)
16             scanf("%d", c+i);
17         memset(dp, 0, sizeof(dp));
18         dp[0] = true;
19         for (int i = 0; i < n; i++){
20             int maxl = a[i] * c[i];
21             if (c[i] == 1){
22                 for (int j = m; j >= a[i]; j--)
23                     if (dp[j - a[i]]) dp[j] = true;
24             }
25             else if (m <= maxl){
26                 for (int j = a[i]; j <= m; j++)
27                     if (dp[j - a[i]]) dp[j] = true;
28             }
29             else for (int j = 0; j < a[i]; j++){               //循环a[i]的同余类
30                 head = tail = 0;
31                 for (int k = j; k <= m; k += a[i]){
32                     while (head != tail && k - q[head] > maxl) head++; //这题单调队列元素优劣性只取决于位置
33                     if (!dp[k]){      //只需踢掉前面已经超出长度的,即第i个硬币全用了也不能由它转移到当前值k
34                         if (head != tail) //单调队列里有元素,可以被他们优化
35                             dp[k] = true;
36                     }
37                     else q[tail++] = k;  //dp[k]为真,可以优化后面的值,放入队列
38                 }
39             }
40         }
41         int ans = 0;
42         for (int i = 1; i <= m; i ++)
43             if (dp[i]) ans ++;
44         printf("%d\n", ans);
45     }
46     return 0;
47 }

POJ 1742 Coins 多重背包单调队列优化

时间: 2024-10-24 01:38:08

POJ 1742 Coins 多重背包单调队列优化的相关文章

POJ 1742 Coins (多重背包)

Coins Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 28448   Accepted: 9645 Description People in Silverland use coins.They have coins of value A1,A2,A3...An Silverland dollar.One day Tony opened his money-box and found there were some

poj1742 Coins(多重背包+单调队列优化)

/* 这题卡常数.... 二进制优化或者单调队列会被卡 必须+上个特判才能过QAQ 单调队列维护之前的钱数有几个能拼出来的 循环的时候以钱数为步长 如果队列超过c[i]就说明队头的不能再用了 拿出来 时刻维护sum表示之前的+v[i]能凑出j来的有几种 注意先进队在更新f */ #include<iostream> #include<cstdio> #include<cstring> #define maxm 100010 #define maxn 110 using

多重背包单调队列优化

for (int i = 1; i <= n; ++i) { Ni = Num[i]; Vi = V[i]; Wi = W[i]; for (int j = 0; j < Vi; ++j) { Head1 = Tail1 = 0; Head2 = Tail2 = 0; Cnt = 0; for (int k = j; k <= m; k += Vi) { if (Tail1 - Head1 == Ni + 1) { if (Q2[Head2 + 1] == Q1[Head1 + 1])

poj 1742 Coins 多重背包变形

传说中的男人八题,是男人就A这八题.有n种面额的硬币,面额个数分别为A_i.C_i,求最多能搭配出几种不超过m的金额? 这是一个多重部分和问题(多重背包问题),放在了<2.3 记录结果再利用的"动态规划" 优化递推关系式>.最基本的做法是: dp[i][j] := 用前i种硬币能否凑成j 递推关系式: dp[i][j] = (存在k使得dp[i - 1][j - k * A[i]]为真,0 <= k <= m 且下标合法) 然后三重循环ijk递推 1 2 3 4

HDU 2844 Coins 多重背包(二进制优化)

点击打开链接 Coins Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 8167    Accepted Submission(s): 3327 Problem Description Whuacmers use coins.They have coins of value A1,A2,A3...An Silverland dolla

hdu 2191 (多重背包的单调队列优化)

多重背包单调队列优化是思想是.普通的dp为 dp[i][j]=max{dp[i-1][j-k*v[i]]+k*w[i]}; 其实你可以发现对能更新j是j和一个剩余类.也就是 0, v[i],2v[i],3v[i] ,4v[i]... 1 ,1+v[i],1+2v[i],1+3v[i] ........... v[i]-1,2*v[i]-1...... 更新值存在一个剩余类中,组与组之间不存在更新.那么实际上我们可以写dp写好这样 dp[b+x*v[i]]=max{ dp[b+k*v[i]]+(x

poj 1742 Coins (多重背包)

http://poj.org/problem?id=1742 n个硬币,面值分别是A1...An,对应的数量分别是C1....Cn.用这些硬币组合起来能得到多少种面值不超过m的方案. 多重背包,不过这题很容易超时,用背包九讲的代码有人说行,但是我提交还是超时,后来参考别人代码加了一些优化才能过,有时间要去搞清楚多重背包的单调队列优化. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using

使用单调队列优化的 O(nm) 多重背包算法

我搜索了一下,找到了一篇很好的博客,讲的挺详细:链接. 解析 多重背包的最原始的状态转移方程: 令 c[i] = min(num[i], j / v[i]) f[i][j] = max(f[i-1][j-k*v[i]] + k*w[i])     (1 <= k <= c[i])  这里的 k 是指取第 i 种物品 k 件. 如果令 a = j / v[i] , b = j % v[i] 那么 j = a * v[i] + b. 这里用 k 表示的意义改变, k 表示取第 i 种物品的件数比

背包问题入门(单调队列优化多重背包

背包问题 写这篇文章主要是为了帮帮新人吧,dalao勿喷.qwq 一般的背包问题问法 每种物品都有一个价值w和体积c.//这个就是下面的变量名,请看清再往下看. 你现在有一个背包容积为V,你想用一些物品装背包使得物品总价值最大. 01背包 多种物品,每种物品只有一个.求能获得的最大总价值. 我们考虑是否选择第i件物品时,是需要考虑前i-1件物品对答案的贡献的. 分析 如果我们不选择第i件物品,那我们就相当于是用i-1件物品,填充了体积为v的背包所得到的最优解. 而我们选择第i件物品的时候,我们要