01背包问题
2017-03-07 20:50
211 查看
01背包的具体的原理(推荐dd大牛的《背包九讲》)
例题:
HDU 2602
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2602
题解:
题目大意:
给你N个物品,一个容量为M的背包。并且给出你N个物品的价值,以及他们的容量,让你求出不超过背包容量的条件下最大的价值。
一道非常典型的01背包的模板题目。
没有优化空间的代码:
已经进行空间优化的代码:
对于这里有一个小技巧,如果题目中要求的是恰好装满背包的话,把dp[0]=0,其他dp[i]=-inf。如果并没有具体要求的话,就将这些全部dp[i]=0。
HDU 2546
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2546
题解:
经典01背包+贪心
代码:
例题:
HDU 2602
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2602
题解:
题目大意:
给你N个物品,一个容量为M的背包。并且给出你N个物品的价值,以及他们的容量,让你求出不超过背包容量的条件下最大的价值。
一道非常典型的01背包的模板题目。
没有优化空间的代码:
#include <bits/stdc++.h> #include <algorithm> using namespace std; #define met(a,b) memset(a,b,sizeof(a)) #define inf 0x3f3f3f3f const int maxn = 1e3+10; int w[maxn],v[maxn]; int dp[maxn][maxn];//最简单的01背包(没有空间的优化) int main() { int t; scanf("%d",&t); while(t--) { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&v[i]); for(int i=1;i<=n;i++) scanf("%d",&w[i]); met(dp,0); for(int i=1;i<=n;i++)//自己感觉这里就是在进行暴力的枚举,每次更新最优解。 for(int j=0;j<=m;j++) { if(j>=w[i])//条件满足的情况下,就进行选择更新。 dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]); else dp[i][j]=dp[i-1][j]; } printf("%d\n",dp [m]); } }
已经进行空间优化的代码:
#include <bits/stdc++.h> #include <algorithm> using namespace std; #define met(a,b) memset(a,b,sizeof(a)) #define inf 0x3f3f3f3f const int maxn = 1e3+10; int w[maxn],v[maxn]; int dp[maxn];//01背包的空间的优化。 int main() { int t; scanf("%d",&t); while(t--) { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&v[i]); for(int i=1;i<=n;i++) scanf("%d",&w[i]); met(dp,0); for(int i=1;i<=n;i++) for(int j=m;j>=0;j--) { if(j>=w[i]) dp[j]=max(dp[j],dp[j-w[i]]+v[i]); } printf("%d\n",dp[m]); } }
对于这里有一个小技巧,如果题目中要求的是恰好装满背包的话,把dp[0]=0,其他dp[i]=-inf。如果并没有具体要求的话,就将这些全部dp[i]=0。
HDU 2546
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2546
题解:
经典01背包+贪心
代码:
#include <bits/stdc++.h> #include <algorithm> using namespace std; #define met(a,b) memset(a,b,sizeof(a)) #define inf 0x3f3f3f3f const int maxn = 1e3+10; int dp[maxn]; int p[maxn]; int main() { int n,m; while(scanf("%d",&n)!=EOF&&n!=0) { for(int i=1;i<=n;i++) scanf("%d",&p[i]); scanf("%d",&m); if(m<5)//这里的是非主流的打法,可以选择后面直接用m-5 printf("%d\n",m); else//这里主要用到的是贪心的思想,将最大的价值直接用5买掉 { m-=5; sort(p+1,p+1+n); met(dp,0); for(int i=1;i<n;i++)//这里因为前面的贪心,所以这里只需要对1到n-1就行了。 for(int j=m;j>=p[i];j--) dp[j]=max(dp[j],dp[j-p[i]]+p[i]); printf("%d\n",m+5-dp[m]-p );//这里记得将原来贪心的那部分减去就行了。 } } }