混合背包问题
二进制优化代码,具体见代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1000010; 5 const int mod = 1e9+7; 6 const int inf = 0x3f3f3f3f; 7 int n,m,v[maxn],w[maxn],dp[maxn]; 8 int cnt; 9 10 int main() 11 { 12 scanf("%d%d",&n,&m); 13 for(int i=1;i<=n;i++){ 14 int a,b,ss; scanf("%d%d%d",&a,&b,&ss); 15 if( ss<0 ) ss=1;//把01背包转换成只有一个的多重背包 16 else if( ss==0 ) ss=m/a;//如果是完全背包,在最优情况下,只能取总体积/该物品体积向下取整 17 18 for(int j=1;j<=ss;j<<=1){ 19 cnt ++; 20 v[cnt] = j*a; 21 w[cnt] = j*b; 22 ss -= j; 23 } 24 if( ss>0 ){ 25 cnt ++; 26 v[cnt] = ss*a; 27 w[cnt] = ss*b; 28 } 29 } 30 31 for(int i=1;i<=cnt;i++){ 32 for(int j=m;j>=v[i];j--){ 33 dp[j] = max(dp[j], dp[j-v[i]]+w[i]); 34 } 35 } 36 cout<<dp[m]<<endl; 37 return 0; 38 }
队列优化代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1000010; 5 const int mod = 1e9+7; 6 const int inf = 0x3f3f3f3f; 7 int n,m,q[maxn],dp[1010][1010]; 8 int cnt; 9 10 int main() 11 { 12 scanf("%d%d",&n,&m); 13 for(int i=1;i<=n;i++){ 14 int a,b,ss; scanf("%d%d%d",&a,&b,&ss); 15 if( ss<0 ) ss=1;//把01背包转换成只有一个的多重背包 16 else if( ss==0 ) ss=m/a;//如果是完全背包,在最优情况下,只能取总体积/该物品体积向下取整 17 18 for(int j=0;j<a;j++){ 19 int head=0, tail=1; 20 q[0] = 0; 21 for(int k=j;k<=m;k+=a){ 22 while( head<tail && q[head]<k-ss*a ) head++; 23 dp[i][k] = dp[i-1][k]; 24 if(head<tail) dp[i][k] = max(dp[i][k], dp[i-1][q[head]]+(k-q[head])/a*b); 25 while( head<tail && dp[i-1][q[tail-1]]+(k-q[tail-1])/a*b<dp[i-1][k] ) tail--; 26 q[tail++] = k; 27 } 28 } 29 } 30 printf("%d\n",dp[n][m]); 31 return 0; 32 }