关于环形DP

环的存储:破环为链
通俗来说,即复制一份长度为n的数列,拓展到2*n的长度,扩展后第n个数和第n+1个数相接,用链模拟环
1 2 3 4 1 2 3 4

 

环形dp的最终值并非同区间dp一样为dp[1][n],因为是环,所以需要从1到n循环,不断更新一个最大值,MAX=max(MAX,dp[i][i+n])
还是用存储时的例子
1 2 3 4 1 2 3 4
1 2 3 4 5 6 7 8(对应下标)
n=4,从1-4,2-6,3-7,4-8都有可能成为最大值
这部分卡了非常久(太弱)

例题:能量项链 传送门

#include<cstdio>
#include<algorithm>
#define MAXN 300
using namespace std;
int n,tail[MAXN],head[MAXN];
int f[MAXN][MAXN];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&head[i]);
        head[i+n]=head[i];
    }
    for(int i=1;i<2*n;i++)
    {
        tail[i]=head[i+1];
    }
    tail[2*n]=head[1];
    for(int len=1;len<=n;len++)
    {
        for(int i=1;i+len<=2*n;i++)
        {
            int j=i+len;
            for(int k=i;k<j;k++)
            {
                f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+head[i]*tail[j]*tail[k]);
            }
        }
    }
    printf("%d",f[1][n]); //问题所在
    return 0;
}
错误示例

正解

#include<cstdio>
#include<algorithm>
#define MAXN 300
using namespace std;
int n,ans,tail[MAXN],head[MAXN],f[MAXN][MAXN];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&head[i]);
        head[i+n]=head[i];
    }
    for(int i=1;i<2*n;i++)
    {
        tail[i]=head[i+1];
    }
    tail[2*n]=head[1];
    for(int len=1;len<=n;len++)
    {
        for(int i=1;i+len<=2*n;i++)
        {
            int j=i+len;
            for(int k=i;k<j;k++)
            {
                f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+head[i]*tail[j]*tail[k]);
            }
        }
    }
    for(int i=1;i<=n;i++)
        ans=max(ans,f[i][i+n-1]);
    printf("%d",ans); //KEY
    return 0;
}

 

posted on 2020-11-06 19:20  月霜  阅读(373)  评论(0)    收藏  举报

导航