1 8 2 2 100 4 4 100 2
400
思路:特别经典地多重背包,先判断把这个东西全部放进背包,如果比背包的容量大,就可以当成完全背包了,如果不是的话,就当成01背包,至于(k=1,2,4,6,8..),是因为
这些数可以组合出任意数。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int t,m,n; int p[105],h[105],c[105]; int dp[105]; void Zp(int c,int w) { int i; for(i=n; i>=c; i--) dp[i]=max(dp[i],dp[i-c]+w); } void Cp(int c,int w) { int i; for(i=c; i<=n; i++) dp[i]=max(dp[i],dp[i-c]+w); } void Mp(int c,int w,int sum) { if(n<=c*sum) { Cp(c,w); return ; } else { int k=1; while(k<=sum) { Zp(k*c,k*w); sum-=k; k*=2; } Zp(sum*c,sum*w); } } int main() { int i,j; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(i=0; i<m; i++) scanf("%d%d%d",&p[i],&h[i],&c[i]); memset(dp,0,sizeof(dp)); for(i=0; i<m; i++) Mp(p[i],h[i],c[i]); printf("%d\n",dp[n]); } }