这题和NOIP的金明的预算方案(?)很像,只不过附件的数量增多了
如果对主件进行一次01背包,再套一层附件的01背包O(n4)肯定会爆。。
所以我们可以先预处理出,对于每个主件,花的时间为k的情况下,最大的经验值,用01背包做
然后再对每个主件进行01背包,这样就去掉了一层循环
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #define maxn 102 5 using namespace std; 6 long long n[maxn*5],v[maxn][maxn*5],c[maxn][maxn*5],t[maxn][maxn*5],f[maxn*5]; 7 int N,T; 8 int main(){ 9 scanf("%d%d", &N, &T); 10 for (int i=1; i<=N; i++){ 11 scanf("%lld%lld%lld", &n[i], &v[i][0], &c[i][0]); 12 for (int j=1; j<=n[i]; j++) 13 scanf("%lld%lld", &v[i][j], &c[i][j]); 14 } 15 memset(t,0,sizeof(t)); 16 memset(f,0,sizeof(f)); 17 for (int i=1; i<=N; i++){ 18 for (int k=T; k>=v[i][0]; k--) 19 t[i][k]=c[i][0]; 20 for (int j=1; j<=n[i]; j++) 21 for (int k=T; k>=v[i][0]+v[i][j]; k--) 22 t[i][k]=max(t[i][k],t[i][k-v[i][j]]+c[i][j]); //第i个主件,k时间能拿到的最大经验值 23 } 24 for (int i=1; i<=N; i++) 25 for (int j=T; j>=v[i][0]; j--) 26 for (int k=j; k>=0; k--) 27 f[j]=max(f[j],f[j-k]+t[i][k]); 28 printf("%lld\n", f[T]); 29 return 0; 30 }