能量項鏈 (區間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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM