能量项链 (区间DP)

能量项链 (区间DP)

问题引入

能量项链 洛谷 P1063

思路

诸如此类不能线性规划的问题要用到区间DP,区间DP一般就是三层循环,第一层表示区间长度(本题即\(n\)),第二层枚举起点并根据第一层区间长度算出区间终点,第三层便在当前区间内枚举决策(即哪两个合并)

本题由于是环,还需破环为列,可以开两倍大的数组,即\(a[i]=a[i+n]\),便可在第n颗珠子时求到第1颗珠子的头标记(也即第n颗珠子的尾标记)

合并珠子即合并左珠\(dp[i][k]\)和右珠\(dp[k+1][j]\),释放能量\(a[i]*a[k+1]*a[j+1]\)(注意\(a[i]\)存放的是第i颗珠子的头标记,所以\(a[k+1]\)才是第k个珠子的尾标记)

例码

#include <iostream> 
#define MAXN 202
#define MAX(a,b) ((a)>(b)?(a):(b))
using namespace std;
int n,a[MAXN],dp[MAXN][MAXN],ans;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i],a[i+n]=a[i];
    for(int len=2;len<=n;len++)//枚举区间长度
        for(int i=1;i+len-1<n*2;i++){//枚举区间起点
            int j=i+len-1;//区间终点
            for(int k=i;k<j;k++)//枚举决策
                dp[i][j]=MAX(dp[i][j], dp[i][k]+dp[k+1][j]+a[i]*a[k+1]*a[j+1]);
        }
    for(int i=1;i<=n;i++)//枚举可能的答案
        ans=MAX(dp[i][i+n-1],ans);
    cout<<ans;
    return 0;
}
posted @ 2018-08-12 11:57  Santiego  阅读(2904)  评论(0编辑  收藏  举报