DAG 上的 DP&环形DP

DAG 上的 DP&环形DP

例1:Naptime

https://www.luogu.com.cn/problem/SP283

解答详见蓝书

简化问题——每天从第1小时开始,到第N小时结束,线性

然后再强制第1小时和第N小时都睡觉,再dp一遍

最后取max

滚动数组滚掉一维

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int N=4000;
int f[2][N][2],n,m,a[N],ans;

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) 
        scanf("%d",&a[i]);
    memset(f,0xcf,sizeof(f));
    f[1][1][1]=f[1][0][0]=0;
    for(int i=2;i<=n;i++)
        for(int j=0;j<=m;j++) {
            f[i&1][j][0]=max(f[(i-1)&1][j][0],f[(i-1)&1][j][1]);
            if(j>=1) f[i&1][j][1]=max(f[(i-1)&1][j-1][1]+a[i],f[(i-1)&1][j-1][0]);
        }
    ans=max(f[n&1][m][1],f[n&1][m][0]);
    memset(f,0xcf,sizeof(f));
    f[1][1][1]=a[1];
    for(int i=2;i<=n;i++)
        for(int j=0;j<=m;j++) {
            f[i&1][j][0]=max(f[(i-1)&1][j][0],f[(i-1)&1][j][1]);
            if(j>=1) f[i&1][j][1]=max(f[(i-1)&1][j-1][1]+a[i],f[(i-1)&1][j-1][0]);
        }
    ans=max(ans,f[n&1][m][1]);
    printf("%d\n",ans);
    return 0;
}

例2:巴比伦塔 The Tower of Babylon

posted @ 2020-08-15 17:25  ke_xin  阅读(29)  评论(0编辑  收藏  举报