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组测试用例,每组测试用例的第一行是两个整数n和m(1<=n<=100, 1<=m<=100),分别表示经费的金额和大米的种类,然后是m行数据,每行包含3个数p,h和c(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;}
- HDOJ 2191 (多重背包/二进制分解/单调队列优化DP)
- 多重背包,二进制优化,单调队列优化
- Dividing(多重背包、单调队列优化dp)
- hdu2191(单调队列优化dp,多重背包)
- poj 1276 多重背包+二进制优化+单调队列优化
- 多重背包模板--二进制优化模板&&单调队列优化模板
- 多重背包的优化 二进制/单调队列解析
- 多重背包(单调队列优化)
- 多重背包(单调队列优化)
- hdu1171 (单调队列优化多重背包)
- 多重背包单调队列优化
- 单调队列优化多重背包
- 单调队列优化多重背包
- 单调队列优化多重背包
- HDOJ(HDU).1059 Dividing(DP 多重背包+二进制优化)
- HDOJ(HDU).2844 Coins (DP 多重背包+二进制优化)
- hdoj 2191 悼念512。。 【多重背包】+【二进制分解】
- 多重背包(单调队列(滑动最大值)+二进制方法)
- Item38 Be aware of varying thread handle destructor behavior
- linux基础命令
- C语言第五次作业练习
- python语句实现文件合并
- 周志华《Machine Learning》学习笔记(11)--聚类
- HDOJ 2191 (多重背包/二进制分解/单调队列优化DP)
- 背包——AtCoder Regular Contest 073 #D
- 集群、分布式环境下5种session处理策略
- LeetCode-313. Super Ugly Number (JAVA)超级丑数
- 永久改变SELINUX安全上下文
- 如何培养卓越的项目推动力
- HTML5学习之表单
- C语言第六次作业练习
- 二分推进算法