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

/*
这题卡常数....
二进制优化或者单调队列会被卡
必须+上个特判才能过QAQ
单调队列维护之前的钱数有几个能拼出来的
循环的时候以钱数为步长
如果队列超过c[i]就说明队头的不能再用了 拿出来
时刻维护sum表示之前的+v[i]能凑出j来的有几种
注意先进队在更新f
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxm 100010
#define maxn 110
using namespace std;
int n,m,v[maxn],c[maxn],f[maxm],ans,q[maxm],head,tail,sum;
int main()
{
    for(;;){
        scanf("%d%d",&n,&m);
        if(n==0&&m==0)break;ans=0;
        for(int i=0;i<=m;i++)f[i]=0;f[0]=1;
        for(int i=1;i<=n;i++)scanf("%d",&v[i]);
        for(int i=1;i<=n;i++)scanf("%d",&c[i]);
        for(int i=1;i<=n;i++){
            if(v[i]*c[i]>=m){
                for(int j=v[i];j<=m;j++)
                    if(f[j-v[i]]&&f[j]==0){
                        ans++;f[j]=1;
                    }
                continue;
            }
            for(int s=0;s<v[i];s++){
                head=1,tail=0,sum=0;
                for(int j=s;j<=m;j+=v[i]){
                    if(tail-head+1>c[i]){
                        sum-=q[head];head++;
                    }
                    q[++tail]=f[j];sum+=f[j];//这里先进队 就是说保证这些队列的f都是上一匹物品更新来的
                    if(sum&&f[j]==0){
                        ans++;f[j]=1;
                    }
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
时间: 2024-10-23 16:29:52

poj1742 Coins(多重背包+单调队列优化)的相关文章

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

http://poj.org/problem?id=1742 题意: 很多硬币,有价值和数量,给出一个上限,问上限内有多少种钱数可以由这些硬币组成. 分析: 好像是楼教主男人八题之一.然后学多重背包单调队列优化时看了别人的程序..所以后来写了就1A了=.= 前一篇小小总结了一下多重背包单调队列优化(http://www.cnblogs.com/james47/p/3894772.html),这里就不写了. 1 #include<cstdio> 2 #include<cstring>

多重背包单调队列优化

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])

POJ1742 Coins[多重背包可行性]

Coins Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 34814   Accepted: 11828 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

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

POJ1742 Coins 多重背包+贪心

Vjudge传送门 $Sol$ 首先发现这是一个多重背包,所以可以用多重背包的一般解法(直接拆分法,二进制拆分法...) 但事实是会TLE,只能另寻出路 本题仅关注“可行性”(面值能否拼成)而不是“最优性”,这是一个特殊之处. 从这里找优化 在“最优性”的问题中,$f[j]$从$f[j]$或$f[j-a[i]]$中转移而来:而在这样的“可行性”问题中,其实只要$f[j]$可行,我们就可以不用考虑$f[j-a[i]$了,也可以反过来说. 于是我们可以考虑一种贪心策略,设$used[j]$表示$f[

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

使用单调队列优化的 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件物品的时候,我们要

[Vijos 1243]生产产品(单调队列优化Dp)

Description 在经过一段时间的经营后,dd_engi的OI商店不满足于从别的供货商那里购买产品放上货架,而要开始自己生产产品了!产品的生产需要M个步骤,每一个步骤都可以在N台机器中的任何一台完成,但生产的步骤必须严格按顺序执行.由于这N台机器的性能不同,它们完成每一个步骤的所需时间也不同.机器i完成第j个步骤的时间为T[i,j].把半成品从一台机器上搬到另一台机器上也需要一定的时间K.同时,为了保证安全和产品的质量,每台机器最多只能连续完成产品的L个步骤.也就是说,如果有一台机器连续完