Luogu-P1063 能量项链

 

题目

题目链接

 

 

测试得分:  100

 

 

主要算法 :  动态规划,区间DP(环状DP)

 

题干:

    环状区间DP板子题

 

应试策略:

  1. 确定状态f[i][j]表示的是合并i-j这几堆吸盘释放的能量的最大值 
  2. 枚举区间长度FORa(l,1,n)
  3. 枚举区间开头for(int i=1,in=2*n-l+1;i<=in;i++)
  4. 状态转移f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+a[i].head*a[k].tail*a[j].tail);
  5. 更新答案 if(l==n) ans=max(ans,f[i][i+n-1]);

 

#include<stdio.h>
#include<stdlib.h>
#define FORa(i,s,e) for(int i=s;i<=e;i++)
#define FORs(i,s,e) for(int i=s;i>=e;i--)

using namespace std;

const int N=100;
struct Node{
    int head,tail;
}a[2*N+2]; 
int n,ans,f[2*N+2][2*N+2];//f[i][j]表示的是合并i-j这几堆吸盘释放的能量的最大值 
inline int max(int fa,int fb){return fa>fb?fa:fb;}
int main()
{
    scanf("%d",&n);
    FORa(i,1,n) scanf("%d",&a[i].head),a[i+n].head=a[i].head;
    for(int i=1;i<2*n;i++) a[i].tail=a[i+1].head;
    a[2*n].tail=a[1].head;
    FORa(l,1,n)//枚举处理吸盘长度 
    {
        for(int i=1,in=2*n-l+1;i<=in;i++)//枚举开头 
        {
            for(int k=i,j=i+l;k<j;k++)//状态转移 
                f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+a[i].head*a[k].tail*a[j].tail);
            if(l==n) ans=max(ans,f[i][i+n-1]);//更新答案 
        }
    }
    printf("%d",ans);
    return 0;
}
/*4
2 3 5 10*/

 

 

总结:

  •   初值
  •   边界
  •   状态转移

 

 

posted @ 2019-08-05 15:59  SeanOcean  阅读(189)  评论(0编辑  收藏  举报