受到背包九讲 有依赖关系的背包问题的启发,最终转化为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,0,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;
}
}