受到背包九讲 有依赖关系的背包问题的启发,最终转化为01背包问题求解
1 2 ... N个车厢
假设M=2
即如果选择1,则必须选择2
如果选择2,则必须选择3
则先把1,2生成一个新的物品1
把2,3生成一个新的物品2
1,2...N这些物品就可以被01背包选择了,但这些物品选取时,还有一些小的限制。
注意下标搞清楚就好了。
#include <iostream> #include <stdio.h> #include <cstring> using namespace std; #define MAX_V (50000+1) #define MAX_F (3 +1) int N,PICKM=3,M; int F[MAX_V][MAX_F]; int Value[MAX_V]; #define printf // void dump() { for(int i=1;i<=N;i++) { printf("\ni=%d:",i); for(int j=1;j<=PICKM;j++) { printf("%4d ",F[i][j]); } } printf("\n"); } int main() { int T; cin >>T; for(int t=1;t<=T;t++) { int maxret = -1; memset(F,sizeof(F)); cin>>N; for(int i=1;i<=N;i++) cin>>Value[i]; // N <= 50000 Value[i] <= 100 cin>>M; // M <= N/3 //M=1 for(int i=1;i<=N-M+1;i++) { int sum = 0; for(int j=i;j<=i+M-1;j++) { sum += Value[j]; } F[i][1] = sum; } printf("after M=1 "); //dump(); for(int _m = 2;_m<=PICKM;_m++) { int s= 1 + M * (_m -2); for(int i= 1;i<=N-M+1;i++) { int t = i - M; printf("i=%d,_m=%d,s=%d,t=%d\n",i,_m,s,t); int _max = 0; //_max代表F[i][_m] for( int k=t;k>=s;k--) { if(F[k][_m-1] +F[i][1] > _max) _max = F[k][_m - 1] + F[i][1]; } F[i][_m] = _max; } printf("after M=%d ",_m); //dump(); } for(int i=1;i<=N-M+1;i++) { if( F[i][PICKM] > maxret) maxret = F[i][PICKM]; } cout<<maxret<<endl; } }