能量项链

题目描述

说明

NOIP 2006 提高组 第一题

这题也是一题区间DP哦

下文先贴出代码,会按照代码来讲解思路

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long  R[300],L[300],N,F[300][300],Ans;//R[]为头标记 ,L[]为尾标记
inline void Read(void)
{
    scanf("%lld",&N);
    for(int i=1; i<=N; ++i)
    {
        scanf("%lld",&R[i]);
        L[i-1]=R[i];//前一个珠子尾标记 为此个珠子的头标记
        R[i+N] =R[i];//存环成链
        L[i-1+N]=L[i-1];
    }
    L[N*2]=R[1];
}
inline void Work(void)
{
    for(int n=1; n<N; ++n)//确定合并
    {
        for(int i=1; i<=N*2-n; ++i)  //确定起点,PS:注意i的循环条件,笔者就是在这里卡了十分钟!!!
        {
            int j=i+n;//确定终点
            for(int k=i; k<j; ++k)//确定中转点
            {
                long long  T=R[i]*R[k+1]*L[j];
                F[i][j]=max(F[i][j],F[i][k]+F[k+1][j]+T);//从第i颗珠子到第j颗珠子的最佳聚合结果 
            }
            if(F[i][j]>Ans)Ans=F[i][j];
        }
    }
}
int main(void)
{
    Read();
    Work();
    printf("%lld",Ans);
    return 0;
}

思路解析:

  1.首先和石子合并的方法一样,先存环成链;

  2.根据题意,本题的初始化条件为F[i][j]=0,因而根据c++的特点,不用再进行初始化

  3.动态转移方程的书写:F[i][j]=max(F[i][j],F[i][k]+F[k+1][j]+R[i]*R[k+1]*L[j]);

    即求合并第 i-k 个珠子和第 k+1-j 个珠子所释放的能量最大值(具体分析此次就不在详解了,如若不明请看:[NOI1995]石子合并

  4.比较问题结果最优值

  恭喜你AC了!!!

  

原文地址:https://www.cnblogs.com/Blacktears/p/9852618.html