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有更深刻的理解。

posted @ 2019-12-11 21:15  DeepJay  阅读(207)  评论(0编辑  收藏  举报