POJ 3624 Charm Bracelet(简单DP,01背包)
Bessie has gone to the mall's jewelry store and spies a charm bracelet. Of course, she'd like to fill it with the best charms possible from the N (1 ≤ N ≤ 3,402) available charms. Each charm i in the supplied list has a weight Wi (1 ≤ Wi ≤ 400), a 'desirability' factor Di (1 ≤ Di ≤ 100), and can be used at most once. Bessie can only support a charm bracelet whose weight is no more than M (1 ≤ M ≤ 12,880).
Given that weight limit as a constraint and a list of the charms with their weights and desirability rating, deduce the maximum possible sum of ratings.
Input
* Line 1: Two space-separated integers: N and M
* Lines 2..N+1: Line i+1 describes charm i with two space-separated integers: Wi and Di
Output
* Line 1: A single integer that is the greatest sum of charm desirabilities that can be achieved given the weight constraints
Sample Input
4 6 1 4 2 6 3 12 2 7
Sample Output
23
题意:
就是一道常见的01背包问题。(01背包就是物品可以取0件或者1件)
题解:
01背包的递推关系式:
dp[i+1][j]表示从0到i这i+1个物品中选出总重量不超过j的物品时总价值的最大值。
dp[0][j]=0
dp[i+1][j]=dp[i][j] (j<w[i])
dp[i+1][j]=max(dp[i][j],dp[i][j-w[i]]+v[i]) (其他)
然后根据这个关系式很容易写出代码。
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int maxn=5000; int v[maxn],w[maxn]; int dp[maxn][13000]; int main() { int n,m; while(cin>>n>>m) { for(int i=0;i<n;i++) cin>>w[i]>>v[i]; for(int i=0;i<n;i++) for(int j=0;j<=m;j++) { if(j<w[i]) dp[i+1][j]=dp[i][j]; else dp[i+1][j]=max(dp[i][j],dp[i][j-w[i]]+v[i]); } cout<<dp[n][m]<<endl; } return 0; }
然而题目要求内存很小,导致MLE了(二维数组太大,需要占用很多内存)。然后发现计算dp第i行时只用到dp第i-1行的数据。因此,可以用压缩成一维数组进行计算。但要注意,应从后住前推算。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=3500; int v[maxn],w[maxn]; int dp[13000]; int main() { int n,m; while(cin>>n>>m) { memset(dp,0,sizeof(0)); for(int i=0;i<n;i++) cin>>w[i]>>v[i]; for(int i=0;i<n;i++) for(int j=m;j>=w[i];j--) { dp[j]=max(dp[j],dp[j-w[i]]+v[i]); } cout<<dp[m]<<endl; } return 0; }