A Mini Locomotive POJ - 1976(01背包变形)
这道题是可以抽象成背包问题,即 选择连续的一段数字放入背包,而一般的背包问题是一个一个数字的选取。
01背包状态转移方程:f[i][j] = max( f[i - 1][j],f[i - c[i] ] + w[i] );
本题状态转移方程 :f[i][j] = max( f[i - 1][j],f[i - m][j - 1] + sum[i] - sum[i - m]); (sum表示前缀和)
值得一提的是这道题是不能用滚动数组的,因为滚动数组逆序递推是基于i由i-1转移,即i-1是i的子问题;
AC代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=2e3+5;
const int N=5e4+5;
int f[N][5],w[N],sum[N];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(f,0,sizeof(f) );
int n,m;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",w+i);
sum[i]=sum[i-1]+w[i];
}
scanf("%d",&m);
for(int i=m;i<=n;i++)
{
for(int j=3;j>=1;j--)
f[i][j]=max(f[i-1][j],f[i-m][j-1]+sum[i]-sum[i-m] );
}
printf("%d\n",f[n][3] );
}
return 0;
}
刚开始写记忆化搜索发现空间不够,后来发现状态和决策出现错误,还是太菜了,需要做更多的题,对dp有更深刻的理解。