题目大意:n个手链,第i个手链的重量wi,价值di,一个人能承受重量M的手链,问最大价值是多少
输入:n m(0<=n<=3402)(0<=m<=12880)
wi di(0<=wi<=400,0<=di<=100)
输出:最大价值
分析:典型的动态规划01背包问题
状态dp[i][j]:前i个手链可选,容量为j时的最大价值
结果:dp[n][m]
初始化:dp[0][j]=0
状态转移方程:dp[i][j]=max{dp[i-1][j],dp[i-1][j-w[i]]+d[i]}
代码:
正常情况下就是01背包二维dp的思想:
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
dp[i][j] = dp[i-1][j];
if(j>=w[i] && dp[i][j]<dp[i-1][j-w[i]]+d[i]){
dp[i][j] =dp[i-1][j-w[i]]+d[i];
}
}
}
但是这道题内存有限制,上述正常做法会超出内存,下面是AC的滚动数组做法:
#include <algorithm>
#include <vector>
using namespace std;
int main(){
int n,m;
scanf("%d %d",&n,&m);
vector<int> w(n+1);
vector<int> d(n+1);
for(int i = 1;i <= n;i++){
scanf("%d %d",&w[i],&d[i]);
}
vector<int> dp(m+1,0);
for(int i = 1;i <= n;i++){
for(int j = m;j >= w[i];j--){ //注意容量j是倒着来的(和完全背包正好相反)
dp[j] = max(dp[j],dp[j - w[i]] + d[i]);
}
}
printf("%d\n",dp[m]);
}