题目描述
即0-1背包,把每个物品只能拿一次改为能拿无数次。
思路
//这个位置的状态是不拿,第一次拿,和第n>1次拿
dp[i][j]=max(max(dp[i-1][j],dp[i-1][j-v[i]]+w[i]),dp[i][j-v[i]]);
拿0次:dp[i-1][j];
拿1次:dp[i-1][j-v[i]]+w[i];
拿2次:dp[i-1][j-v[i]*2]+w[i]*2;
拿3次:dp[i-1][j-v[i]*3]+w[i]*3;
拿n次:dp[i-1][j-v[i]*n]+w[i]*n;
在拿了一次之后:dp[i][j]更新为dp[i-1][j-v[i]]+w[i];
拿第二次时可以直接拿第一次拿的结论d[i][j-v[i]]直接转移。
一维数组优化
#include <bits/stdc++.h>
using namespace std;
int dp[1000];
int main(){int w[110],v[110];int t,m;cin>>t>>m;for(int i=1;i<=m;i++){cin>>w[i]>>v[i];}for(int i=1;i<=m;i++){for(int j=0;j<=t;j++){//0-1背包是从后往前,千万不要弄混if(j>=w[i]){dp[j]=max(dp[j],dp[j-w[i]]+v[i]);}else{dp[j]=dp[j];}}}
/* for(int i=0;i<=m;i++){for(int j=0;j<=t;j++){cout<<dp[i][j]<<" ";}cout<<endl;}
*/ cout<<dp[t];return 0;
}