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-k)*w[i] }=max{dp[b+k*v[i]]-k*w[i]}+x*w[i] ;  (x-c[i]<=k && k<=x)

实际上一个j对于一个x和b,那么可以看出实际上就是几率一段x之前的c[i]区间内的最值。这是一个很明显的单调队列优化。

#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <string>
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;
typedef __int64 LL;
const int mmax  = 1000010;
const int inf = 0x3fffffff;
int p[110],h[110],c[110];
int dp[110][110];
int Q[110];
int head,tail;
void add(int b,int i,int k)
{
    while(head<tail &&
          dp[i-1][b+Q[tail-1]*p[i]]-Q[tail-1]*h[i]<=dp[i-1][b+k*p[i]]-k*h[i])
        tail--;
    Q[tail++]=k;
}
int main()
{
    int n,m,T;
    cin>>T;
    while(T--)
    {
        scanf("%d %d",&n,&m);
        for(int i=1;i<=m;i++)
            scanf("%d %d %d",&p[i],&h[i],&c[i]);
        memset(dp,0,sizeof dp);
        for(int i=1;i<=m;i++)
        {
            for(int j=0;j<p[i];j++)
            {
                head=tail=0;
                for(int k=0;j+k*p[i]<=n;k++)
                {
                    add(j,i,k);
                    if( k-c[i]-1== Q[head] )
                    {
                        head++;
                    }
                    dp[i][j+k*p[i]]=dp[i-1][j+Q[head]*p[i]]-Q[head]*h[i]+k*h[i];
                }
            }
        }
        int ans=0;
        for(int i=0;i<=n;i++)
            ans=max(ans,dp[m][i]);
        cout<<ans<<endl;

    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-06 16:39:52

hdu 2191 (多重背包的单调队列优化)的相关文章

hdu 2191 多重背包 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活

http://acm.hdu.edu.cn/showproblem.php?pid=2191 New~ 欢迎“热爱编程”的高考少年——报考杭州电子科技大学计算机学院关于2015年杭电ACM暑期集训队的选拔 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 17930    Accepted

HDU 2191 多重背包

悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 22865    Accepted Submission(s): 9661 Problem Description 急!灾区的食物依然短缺!为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市

hdu 2191多重背包

悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 22553    Accepted Submission(s): 9524 Problem Description 急!灾区的食物依然短缺!为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市

hdu 2191 多重背包,自己写模板

背景:wa了几次,都是小失误:把i--写成i++之类的,写的时候一定要想到具体用意.还有就是一定要至少写三组测试数据!!!!!!! 学习:模板化写多重背包. #include<cstdio> #include<iostream> #include<cstring> using namespace std; int t,v,n; int c[109],w[109],num[109],F[109]; void zeroonebag(int cost,int weight){

hdu 5945 Fxx and game 单调队列优化dp

Fxx and game Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) Problem Description Young theoretical computer scientist Fxx designed a game for his students. In each game, you will get three integers X,k,t.In each s

使用单调队列优化的 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 种物品的件数比

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

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

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

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

HDU 4122 Alice&#39;s mooncake shop 单调队列优化dp

Alice's mooncake shop Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4122 Description The Mid-Autumn Festival, also known as the Moon Festival or Zhongqiu Festival is a popular harvest festival celebrated by Ch