1)都是一维数组,但是状态转移方程的for循环稍有不同。都是利用倒序时 每一种物品都只放一个的特性,前者是该类物品放k次每次都放一个,后者是该类物品放一次 一次从1到k 放入个数依次增大
#include <iostream> #include <string.h> const int maxn=110; int dp[maxn]; int money[maxn]; int weight[maxn]; int number[maxn]; using namespace std; int main() { int kase; cin>>kase; while(kase--){ int n,m; cin>>n>>m; for(int i=1;i<=m;i++){ cin>>money[i]>>weight[i]>>number[i]; } memset(dp,0,sizeof(dp)); for(int i=1;i<=m;i++){ int minn=min(number[i],n/money[i]); for(int k=1;k<=minn;k++){ for(int j=n;j>=money[i];j--){//注意倒序! dp[j]=max(dp[j],dp[j-money[i]]+weight[i]); } } } cout<<dp[n]<<endl; } }
OR
#include <iostream> #include <string.h> const int maxn=110; int dp[maxn]; int money[maxn]; int weight[maxn]; int number[maxn]; using namespace std; int main() { int kase; cin>>kase; while(kase--){ int n,m; cin>>n>>m; for(int i=1;i<=m;i++){ cin>>money[i]>>weight[i]>>number[i]; } memset(dp,0,sizeof(dp)); for(int i=1;i<=m;i++){ for(int j=n;j>=money[i];j--){//注意倒序! for(int k=1;k<=number[i]&&(k*money[i]<=j);k++){ dp[j]=max(dp[j],dp[j-money[i]*k]+weight[i]*k); } } } cout<<dp[n]<<endl; } }
#include <iostream> #include <string.h> using namespace std; const int maxn=110; int dp[maxn][maxn]; int money[maxn]; int weight[maxn]; int number[maxn]; int main() { int kase; cin>>kase; while(kase--){ int n,m; cin>>n>>m; for(int i=1;i<=m;i++){ cin>>money[i]>>weight[i]>>number[i]; } memset(dp,0,sizeof(dp)); for(int i=1;i<=m;i++){ for(int j=0;j<=n;j++){ int g=dp[i-1][j]; for(int k=0;k<=j/money[i]&&k<=number[i];k++){ g=max(g,dp[i-1][j-money[i]*k]+weight[i]*k); } if(j<money[i]){ dp[i][j]=dp[i-1][j];//不要忘记!!!该类物品因体积原因放不进去时,此时背包的状态,也要继承上一个物品放置后的状态 } else dp[i][j]=g; } } int minn=0; for(int i=1;i<=n;i++){ minn=max(minn,dp[m][i]); } cout<<minn<<endl; } return 0; }
2)
Description
Input
Output
Sample Input
1 8 2 2 100 4 4 100 2
Sample Output
400