背包问题

AcWing 6.多重背包问题 III

扶醉桌前 提交于 2019-12-04 18:43:47
#include<iostream> #include<algorithm> #include<cstring> using namespace std ; const int N=200010; int n,m; int f[N],g[N],q[N]; int main() { cin>>n>>m; for(int i=0; i<n; i++) { int c,w,s; cin>>c>>w>>s; memcpy(g,f,sizeof f); for(int j=0; j<c; j++) { int hh=0,tt=-1; for(int k=j; k<=m; k+=c) { f[k]=g[k]; if(hh<=tt&&k-s*c>q[hh]) hh++; if(hh<=tt)f[k]=max(f[k],g[q[hh]]+(k-q[hh])/c*w); while(hh<=tt&&g[q[tt]]-(q[tt]-j)/c*w<=g[k]-(k-j)/c*w) tt--; q[++tt]=k; } } } cout<<f[m]<<endl; return 0; } 来源: https://www.cnblogs.com/QingyuYYYYY/p/11878208.html

AcWing 7.混合背包问题

隐身守侯 提交于 2019-12-04 18:43:38
#include<bits/stdc++.h> using namespace std ; const int N=1010; int n,m; int f[N]; struct Thing { int kind;//记录背包种类 int v,w; }; vector<Thing>things; int main() { cin>>n>>m; for(int i=0; i<n; i++) { int v,w,s; cin>>v>>w>>s; if(s<0) things.push_back({-1,v,w});//01背包 else if(s==0) things.push_back({0,v,w});//完全背包 else {//多重背包 二进制优化 转换为01背包 for(int k=1; k<=s; k*=2) { s-=k; things.push_back({-1,v*k, w*k}); } if(s>0) things.push_back({-1,v*s,w*s}); } } for(auto thing:things) { if(thing.kind<0) {//01背包 for(int j=m; j>=thing.v; j--) f[j]=max(f[j],f[j-thing.v]+thing.w); } else {//完全背包 for(int j=thing.v

AcWing 8.二维费用的背包问题

江枫思渺然 提交于 2019-12-04 18:43:30
#include<iostream> #include<algorithm> #include<cstring> using namespace std ; const int N=110; int n,v,m; int f[N][N]; int main() { cin>>n>>v>>m; for(int i=0;i<n;i++) { int a,b,c; cin>>a>>b>>c; for(int j=v;j>=a;j--) for(int k=m;k>=b;k--) f[j][k]=max(f[j][k],f[j-a][k-b]+c); } cout<<f[v][m]<<endl; return 0; } 来源: https://www.cnblogs.com/QingyuYYYYY/p/11878218.html

HDU 2844 Coins 多重背包

本秂侑毒 提交于 2019-12-04 17:45:43
HDU 2844 Coins 多重背包 题意 给你n种硬币,每个硬币的金额为 \(Ai\) ,数量为 \(Ci\) ,然后给你一个范围 \(m\) ,问在使用这些硬币可以组成多少种金额,要求组成的金额在 \((1, m)\) 范围内。 解题思路 使用多重背包来进行解决这个问题。这样我们能够获得每种金额(可以看作背包的容量)下使用硬币组成的最多的金额数量。二重背包结束后,然后使用for循环,遍历这里dp里面 \(dp[i]==i\) 的个数,这个个数就是答案。 代码实现 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=107; //硬币的种类数量 const int maxm=1e5+7; //金额的最大范围 int a[maxn], c[maxn]; int n, m; int dp[maxm]; int main() { while(scanf("%d%d", &n, &m) && (n+m)!=0) { for(int i=1; i<=n; i++) scanf("%d", &a[i]); for(int i=1; i<=n; i++) scanf("%d", &c[i]); memset(dp, 0, sizeof(dp)); /

AcWing 4. 多重背包问题

别说谁变了你拦得住时间么 提交于 2019-12-04 16:17:59
朴素 数据范围小 //数据范围小 #include<iostream> #include<algorithm> using namespace std ; const int N=110; int n,m; int v[N],w[N],s[N]; int f[N][N]; int main() { cin>>n>>m; for(int i=1; i<=n; i++) cin>>v[i]>>w[i]>>s[i]; for(int i=1; i<=n; i++) for(int j=0; j<=m; j++) for(int k=0; k<=s[i]&&k*v[i]<=j; k++) f[i][j] = max(f[i][j], f[i-1][j - v[i]*k] + w[i]*k); cout<<f[n][m]<<endl; } 来源: https://www.cnblogs.com/QingyuYYYYY/p/11873180.html

AcWing 3. 完全背包问题

社会主义新天地 提交于 2019-12-04 16:17:42
朴素 #include<iostream> #include<algorithm> using namespace std ; const int N=1010; int n,m; int v[N],w[N]; int f[N][N]; int main() { cin>>n>>m;//n个物品 最大体积位m for(int i=1; i<=n; i++) cin>>v[i]>>w[i]; for(int i=1; i<=n; i++) for(int j=0; j<=m; j++) for(int k=0; k*v[i]<=j; k++)//选k个第i个物品 f[i][j]=max(f[i][j],f[i-1][j-v[i]*k]+k*w[i]); cout<<f[n][m]<<endl; return 0; } 优化二维 //01背包从i-1转移过来 而完全背包是从第i层转移过来 #include <iostream> #include <algorithm> using namespace std; const int N = 1010; int n, m; int v[N], w[N]; int f[N][N]; int main() { cin >> n >> m; for (int i = 1; i <= n; i ++ ) cin >> v[i] >> w[i];

AcWing 5. 多重背包问题 II

主宰稳场 提交于 2019-12-04 16:17:34
//二进制优化 最后变为01背包 #include <iostream> #include <algorithm> using namespace std; const int N = 12010, M = 2010; int n, m; int v[N], w[N]; int f[M]; int main() { cin >> n >> m; int cnt = 0; for (int i = 1; i <= n; i ++ ) { int a, b, s; cin >> a >> b >> s; int k = 1; while (k <= s) { cnt ++ ; v[cnt] = a * k; w[cnt] = b * k; s -= k; k *= 2; } if (s > 0) { cnt ++ ; v[cnt] = a * s; w[cnt] = b * s; } } n = cnt; for (int i = 1; i <= n; i ++ ) for (int j = m; j >= v[i]; j -- ) f[j] = max(f[j], f[j - v[i]] + w[i]); cout << f[m] << endl; return 0; } 来源: https://www.cnblogs.com/QingyuYYYYY/p/11873181.html

java - 算法 -动态规划 - 01背包

对着背影说爱祢 提交于 2019-12-04 15:38:36
- -一个月前没搞明白,最近再学习一遍搞明白了。 问题: 给定3个物品 a 价值1000, 重量1kg b 价值2000, 重量4kg c 价值1500, 重量3kg 用容量为4kg的背包最多可以装价值多少的物品? 背包问题就是类似这种给定容量求最优解的问题,有很多种,这里说的是01背包问题。 01背包:所有物品只有一个,只所以背包中任意物品的的数量只可能是0 或者 1。 动态规划思路: 当前情况的思考建立在之前的思考之上。 01背包的逻辑思考过程: - -之前网上各种版本都是来个表格然后就开始代码了。。。一脸懵逼 我先假设只考虑第1个物品a,这样我就可以得到: 背包最大容量为0, 1,2,3,4时,最大价值为0, 1000,1000,1000,1000 然后再考虑前2个物品(a 和 b) 先考虑: 背包最大容量为0,1,2,3时, b装不下,所以还是用只考虑前1个物品时的策略,可以得到0, 1000,1000,1000 背包最大容量为4时,b可以装下了,这时候就面临选择,比较:是考虑往背包中加入b时的价值高, 还是只考虑前1个物品时的价值高。 1. 假设加入了b: 背包剩余可用的容量是: 背包最大容量 - b占用的容量 = 4 - 4 = 0; 此时背包物品的最大价值是: b的价值 + 剩余容量所能存放的还没加入b之前的最大值。 而剩余容量所能存放的还没加入b之前的最大值

0x50 动态规划

a 夏天 提交于 2019-12-04 13:19:45
0x51 线性DP LIS 最长上升子序列,给定一个长度为 \(N​\) 序列 \(A​\) ,求出数值单调递增的子序列长度最长是多少 \(O(n^2)\) 做法 \(f[i]\) 表示以 \(i\) 结尾的最长上升子序列长度是多少 自然转移方程为 \(f[i]=max(f[j])+1,(1\le j < i,A[j]<A[i] )\) for( register int i = 1 ; i <= n ; i ++ ) { f[i] = 1; for( register int j = 1 ; j < i ; j ++) { if( a[j] >= a[i] ) continue; f[i] = max( f[i] , f[j] + 1 ); } } \(O(nlog_n)\) 做法 对于 \(O(n^2)\) 的做法,我们每次都枚举 假设我们已经求的一个最长上升子序列,我们要进行转移,如果对于每一位,在不改变性质的情况下,每一位越小,后面的位接上去的可能就越大,所以对于每一位如果大于末尾一位,就把他接在末尾,否则在不改变性质的情况下,把他插入的序列中 for( register int i = 1 ; i <= n ; i ++ ) { if( a[i] > f[ tot ] ) f[ ++ tot ] = a[i]; else *upper_bound( f + 1 , f +

浅谈背包【复习】

独自空忆成欢 提交于 2019-12-04 13:15:22
二进制优化分组背包: http://acm.hdu.edu.cn/showproblem.php?pid=2844 分析: 没什么好说的就是模板 code by wzxbeliever: #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cctype> #define ll long long #define il inline #define ri register int #define lowbit(x) x&(-x) using namespace std; const int maxn=105; const int maxx=100005; int n,m,cnt,ans; int dp[maxx],v[maxn*40],val[maxn],num[maxn]; int main(){ scanf("%d%d",&n,&m); while(n||m){ cnt=ans=0; memset(dp,0,sizeof dp); for(ri i=1;i<=n;i++)scanf("%d",&val[i]); for(ri i=1;i<=n;i++)scanf("%d",&num[i]); for(ri i=1;i<=n;i++) for(ri j=1;j<=num