HDOJ 2191 (多重背包/二进制分解/单调队列优化DP)

来源:互联网 发布:wp login.php 编辑:程序博客网 时间:2024/06/02 22:05

悼念512汶川大地震遇难同胞——珍惜现在,感恩生活

Time Limit: 1000/1000 MS(Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 28982    Accepted Submission(s): 12110

Problem Description

急!灾区的食物依然短缺!
为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品,其价格不等,并且只能整袋购买。
请问:你用有限的资金最多能采购多少公斤粮食呢?

后记:
人生是一个充满了变数的生命过程,天灾、人祸、病痛是我们生命历程中不可预知的威胁。
月有阴晴圆缺,人有旦夕祸福,未来对于我们而言是一个未知数。那么,我们要做的就应该是珍惜现在,感恩生活——
感谢父母,他们给予我们生命,抚养我们成人;
感谢老师,他们授给我们知识,教我们做人
感谢朋友,他们让我们感受到世界的温暖;
感谢对手,他们令我们不断进取、努力。
同样,我们也要感谢痛苦与艰辛带给我们的财富~

 

Input

输入数据首先包含一个正整数C,表示有C组测试用例,每组测试用例的第一行是两个整数nm(1<=n<=100, 1<=m<=100),分别表示经费的金额和大米的种类,然后是m行数据,每行包含3个数phc(1<=p<=20,1<=h<=200,1<=c<=20),分别表示每袋的价格、每袋的重量以及对应种类大米的袋数。

 

 

Output

对于每组测试数据,请输出能够购买大米的最多重量,你可以假设经费买不光所有的大米,并且经费你可以不用完。每个实例的输出占一行。

 

 

Sample Input

1

8 2

2 100 4

4 100 2

 

 

Sample Output

400


多重背包(时间复杂度O(v*∑c[i]))(15ms)

#include <bits/stdc++.h>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(int i=(a);i<=(b);++i)const int maxn = 105;const int mod = 9973;const int INF = 0x3f3f3f3f;const double eps = 1e-6;#define ll long long#define rush() int T;scanf("%d",&T);while(T--)int p[maxn],h[maxn],c[maxn];int dp[maxn];int main(){    int n,m;    rush()    {        scanf("%d%d",&n,&m);        for(int i=0;i<m;i++)        {            scanf("%d%d%d",&p[i],&h[i],&c[i]);        }        mst(dp,0);        for(int i=0;i<m;i++)            for(int j=1;j<=c[i];j++)                for(int k=n;k>=p[i];k--)                    dp[k]=max(dp[k],dp[k-p[i]]+h[i]);        printf("%d\n",dp[n]);    }    return 0;}


二进制优化转化为01背包 (时间复杂度O(v*∑logc[i])  (0ms)

#include <bits/stdc++.h>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(int i=(a);i<=(b);++i)const int maxn = 105;const int mod = 9973;const int INF = 0x3f3f3f3f;const double eps = 1e-6;#define ll long long#define rush() int T;scanf("%d",&T);while(T--)int p[maxn],h[maxn],c[maxn];int dp[maxn];struct node{    int v,w;}s[maxn*10];int main(){    int n,m;    rush()    {        scanf("%d%d",&n,&m);        for(int i=0;i<m;i++)        {            scanf("%d%d%d",&p[i],&h[i],&c[i]);        }        int cnt=0;        for(int i=0;i<m;i++)        {            for(int k=1;k<=c[i];k*=2)            {                s[cnt].v=p[i]*k;                s[cnt++].w=h[i]*k;                c[i]-=k;            }            if(c[i])            {                s[cnt].v=p[i]*c[i];                s[cnt++].w=h[i]*c[i];            }        }        mst(dp,0);        for(int i=0;i<cnt;i++)            for(int j=n;j>=s[i].v;j--)                dp[j]=max(dp[j],dp[j-s[i].v]+s[i].w);        printf("%d\n",dp[n]);    }    return 0;}


单调队列优化DP(时间复杂度O(n*m))(0ms)


首先,对于第i件物品,如果已知体积为p,价值为h,数量为c,那么可以按照p的余数,将当前的体积J分成p组(0,1,....p-1)。

对于任意一组,可以得到转移方程:f[i*p+c]=f[k*p+c]+(i-k)*h,其中c是p组分组中的任意一个

令f[i*p+c]=dp[i],那么就得到dp[i]=dp[k]+(i-k)*h (k>=i-K)

将dp[k]-k*h看做是优化函数,那么就可以运用单调队列来优化了


#include <bits/stdc++.h>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(int i=(a);i<=(b);++i)const int maxn = 105;const int mod = 9973;const int INF = 0x3f3f3f3f;const double eps = 1e-6;#define ll long long#define rush() int T;scanf("%d",&T);while(T--)int f[maxn],dp[maxn];int a[maxn];int main(){    int n,m;    int p,h,c;    int head,tail;    rush()    {        scanf("%d%d",&n,&m);        mst(dp,0);        for(int i=0;i<m;i++)        {            scanf("%d%d%d",&p,&h,&c);            if(c>n/p)                c=n/p;            for(int k=0;k<p;k++)    //分成p份            {                head=tail=0;                for(int j=0;j<=(n-k)/p;j++)                {                    int x=j;                    int y=dp[j*p+k]-j*h;                     while(head<tail&&y>=f[tail-1])                        tail--;                    a[tail]=x;   //记录下标                    f[tail++]=y;                    while(a[head]<j-c)                        head++;                    dp[j*p+k]=f[head]+j*h;                }            }        }        printf("%d\n",dp[n]);    }    return 0;}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 咸鱼违规被投诉侵犯商标权怎么办 房子买了70年后怎么办 买房付完首付后怎么办 手机b站忘记密码怎么办 护士电子注册没有激活码怎么办 大王卡变3g网是怎么办 无法解析服务器的dns地址怎么办 笔记本dns辅服务器未响应怎么办 原营业执照注销法人没在怎么办? 加盟骗局公安局工商局不管怎么办 发现老婆衣柜里有避孕套怎么办 2岁宝宝爱舔东西怎么办 痔疮手术后痛疼怎么办 长了内痔疮该怎么办 淘宝卖家遇到恶意买家怎么办 淘宝遇到恶意买家拍单怎么办 淘宝遇到买家恶意搞坏商品怎么办 木油味道很重怎么办 床垫外面布坏了怎么办 淘宝店铺动态评分低怎么办 实创倒闭返款怎么办 qq红包忘记支付密码怎么办 qq红包支付密码忘了怎么办 个人卖东西人家要发票怎么办 打了欠条找不到人怎么办 公章掉进水里了怎么办 手游吃鸡限制登入15分钟怎么办 宝宝的小鸡淹了怎么办 宝宝小鸡底下淹了怎么办 4岁宝宝拉稀水怎么办 2岁半宝宝对眼怎么办 孩子在幼儿园中午不睡觉怎么办 20天婴儿拉稀水怎么办 3个月婴儿拉水怎么办 两岁宝宝拉水怎么办 1岁半宝宝拉水怎么办 5周孩子小鸡长脂肪粒怎么办 小孩丁丁长歪了怎么办 2个月的婴儿咳嗽怎么办 2个月的宝宝干咳怎么办 2月宝宝感冒咳嗽怎么办