洛谷 P1063 能量项链 区间DP

在这里插入图片描述
思路:区间DP,这道题的描述感觉还是很复杂的,不妨这样想:给定一个数列,首先扩展成两倍的长度,每三个数可以进行合并,合并之后两端的数保留,因此,f[i][j]f[i][j] 表示 [i,j][i,j] 区间的最大能量,e[i]e[i] 表示第 ii 个数的值,则:

f[i][j]=max(f[i][j],f[i][k]+f[k][j]+e[i]e[k]e[j]) f[i][j]=\max(f[i][j],f[i][k]+f[k][j]+e[i]*e[k]*e[j])

要注意中间的 kk 是两区间共享的,然后就是枚举长度时要枚举到 n+1n+1,因为头尾可以共享。

#include<iostream>
#include<cstdio>
#include<algorithm>
#define MAXN 220
using namespace std;
int res,n,e[MAXN],f[MAXN][MAXN];
int main(){
#ifdef WINE
    freopen("data.in","r",stdin);
#endif
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&e[i]);
        e[n+i]=e[i];
    }
    for(int len=3;len<=n+1;len++){ // 注意点1:长度要到 n+1
        for(int i=1;i<=n*2-2;i++){ // 注意点2:起始位置遍历拓展后的长度
            int j=i+len-1;
            if(j>2*n)break;
            for(int k=i+1;k<j;k++) // 中间的 k 是共用的
                f[i][j]=max(f[i][j],f[i][k]+f[k][j]+e[i]*e[k]*e[j]);
            if(len==n+1)res=max(res,f[i][j]);
        }
    }
    printf("%d\n",res);
    return 0;
}

posted @ 2020-06-19 13:47  winechord  阅读(74)  评论(0编辑  收藏  举报