On multiple backpack and optimization

Template Source: codevs 5429

According to the relevant state transition equation knapsack problem, we can easily write simple algorithm

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 inline int read() {
 7     int ret=0;
 8     int op=1;
 9     char c=getchar();
10     while(c<'0'||c>'9') {if(c=='-') op=-1; c=getchar();}
11     while(c<='9'&&c>='0') ret=ret*10+c-'0',c=getchar();
12     return ret*op;
13 }
14 int n,m;
15 int c[7010],v[7010],num[7010];
16 int f[7010];
17 int main() {
18     n=read(); m=read();
19     for(int i=1;i<=n;i++) {
20         c[i]=read(); v[i]=read(); num[i]=read();
21     }
22     for(int i=1;i<=n;i++)
23         for(int j=m;j>=c[i];j--)
24             for(int k=0;k<=num[i];k++)
25                 if(j-c[i]*k>=0)
26                     f[j]=max(f[j],f[j-c[i]*k]+v[i]*k);
27     printf("%d\n",f[m]);
28     return 0;
29 }
TLE Code

In simple algorithm, we enumerate the number of each item as decision-making, so much waste of time, we can split the items instead of binary enumeration, specifically, for example, a certain number of items was 10, then we will this article resolved into 1,2,4,3 number (equivalent to the number of four articles 10 into the article), then this problem is transformed into 01 knapsack problem. Time complexity is greatly reduced.

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 inline int read() {
 7     int ret=0;
 8     int op=1;
 9     char c=getchar();
10     while(c<'0'||c>'9') {if(c=='-') op=-1; c=getchar();}
11     while(c<='9'&&c>='0') ret=ret*10+c-'0',c=getchar();
12     return ret*op;
13 }
14 int n,m,tot;
15 int f[7010],c[100010],v[100010];
16 int main() {
17     n=read(); m=read();
18     for(int i=1;i<=n;i++) {
19         int    x=read(),y=read(),z=read();
20         int base=1;
21         while(z>=base) {
22             c[++tot]=x*base;
23             v[tot]=y*base;
24             z-=base;
25             base<<=1;
26         }
27         if(z>0) {
28             c[++tot]=z*x;
29             v[tot]=z*y;
30         }
31     }
32     for(int i=1;i<=tot;i++)
33         for(int j=m;j>=c[i];j--)
34             f[j]=max(f[j],f[j-c[i]]+v[i]);
35     printf("%d\n",f[m]);
36     return 0;
37 }
TLE Code better

 We continue to consider optimization DP, we will state j according to the number I c [i] grouping, obviously, when i is constant, the state of different groups can not be transferred to each other.

We will reverse the cycle j, for each of the remainder to u∈ [0, c [i] -1], reverse circulation p, so that the state j = u + p * c [i].

 So we get a new state transition equation:

 Fence analogy a problem, we can use monotonous queue optimization, time and complexity of this algorithm is equal ordinary backpack, by this question.

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 typedef long long ll;
 7 int n,m,c[7010],v[7010],num[7010],f[7010];
 8 int q[7010];
 9 inline int read() {
10     int ret=0;
11     int op=1;
12     char c=getchar();
13     while(c<'0'||c>'9') {if(c=='-') op=-1; c=getchar();}
14     while(c<='9'&&c>='0') ret=ret*10+c-'0',c=getchar();
15     return ret*op;
16 }
17 inline int calc(int i,int u,int k) {
18     return f[u+k*c[i]]-k*v[i];
19 }
20 int main() {
21     n=read(); m=read();
22     memset(f,0xcf,sizeof(f));
23     f[0]=0;
24     for(int i=1;i<=n;i++) {
25         c[i]=read(); v[i]=read(); num[i]=read();
26         for(int u=0;u<c[i];u++) {
27             int l=1,r=0;
28             int maxx=(m-u)/c[i];
29             for(int k=maxx-1;k>=max(0,maxx-num[i]);k--) {
30                 while(l<=r&&calc(i,u,q[r])<=calc(i,u,k)) r--;
31                 q[++r]=k;
32             }
33             for(int p=maxx;p>=0;p--) {
34                 while(l<=r&&q[l]>p-1) l++;
35                 if(l<=r) f[u+p*c[i]]=max(f[u+p*c[i]],calc(i,u,q[l])+p*v[i]);
36                 if(p-num[i]-1>=0) {
37                     while(l<=r&&calc(i,u,q[r])<=calc(i,u,p-num[i]-1)) r--;
38                     q[++r]=p-num[i]-1;
39                 }
40             }
41         }
42     }
43     int ans=0;
44     for(int i=1;i<=m;i++)
45         ans=max(ans,f[i]);
46     printf("%d\n",ans);
47     return 0;
48 }
AC Code

 

Guess you like

Origin www.cnblogs.com/shl-blog/p/10990625.html