JDOJ-1089: 能量项链

[文章目录]

Description

给你一个序列,首尾相连成一个环,每个位置有head[i],tail[i]的值,并且head[i]==tail[i-1],每次将两个相邻位置上的值合并,收益为head[i]*tail[i]*tail[i+1]。新形成上的位置的head[new]=head[i],tail[new]=tail[i+1],问合并成最后一个时最大的收益。

由于有环的存在,所以一开始想到加倍然后进行区间DP,也就是枚举大区间断开端点形成的两个小区间更新。然而,由于每次要抠出长度为n的序列,O(n4)感觉会T,并且还进行了很多重复性的更新。

正解的话,直接在环上区间DP,这样的话,每次取模,也可做。不过就要注意一下循环的继续条件,还有一定记住中间只要编号变动都要取模。O(n3)裸过。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n,head[110],tail[110],ans=-1<<30;
int dp[110][110];
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&head[i]);
        tail[(i-1+n)%n]=head[i];
    }
    for(int i=1;i<n;i++)
        for(int l=0;l<n;l++)
        {
            int r=(l+i)%n;
            for(int j=l;j!=r;j=(j+1)%n)
                dp[l][r]=max(dp[l][r],dp[l][j]+dp[(j+1)%n][r]+head[l]*tail[j]*tail[r]);
        }
    for(int i=0;i<n;i++)
        ans=max(ans,dp[i][(i+n-1)%n]);
    printf("%d",ans);
    return 0; 
}

发表评论

邮箱地址不会被公开。 必填项已用*标注