题目网址:https://www.luogu.com.cn/problem/P1063ios
题意大体是:给定一个序列An,第i个元组表示为(Ai,Ai+1),序列位置不变,当合并一个区间[l,l+1]时开销是Al*Al+1*Al+2,问合并整个序列的最大开销。一看就是区间dp,顺便借助记忆化减小搜索的冗余。题目中的项链是环状的,能够经过拼接相同的序列在元序列以后构造出一条链状的序列。代码以下:c++
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef unsigned int ui; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define pf printf 7 #define mem(a) memset(a,0,sizeof(a)) 8 #define prime1 1e9+7 9 #define prime2 1e9+9 10 #define scand(x) scanf("%llf",&x) 11 #define f(i,a,b) for(int i=a;i<=b;i++) 12 #define scan(a) scanf("%d",&a) 13 #define dbg(args) cout<<#args<<":"<<args<<endl; 14 #define pb(i) push_back(i) 15 #define ppb(x) pop_back(x) 16 #define maxn 300 17 int n,m,t,a[maxn],ans=0; 18 int dp[maxn][maxn]; 19 int dfs(int l,int r)//计算[l,r]区间合并的开销 20 { 21 if(l==r)return 0;//单个的没有开销 22 if(dp[l][r])return dp[l][r]; 23 if(l==r-1) return a[l]*a[l+1]*a[r+1];//最小子问题,合并区间长度为2的两个 24 int res=0; 25 f(i,l,r-1) 26 { 27 res=max(res,dfs(l,i)+dfs(i+1,r)+a[l]*a[i+1]*a[r+1]);//枚举两个子区间,有点分治的意味 28 } 29 return dp[l][r]=res; 30 } 31 int main() 32 { 33 //freopen("input.txt","r",stdin); 34 //freopen("output.txt","w",stdout); 35 std::ios::sync_with_stdio(false); 36 scan(n); 37 mem(dp); 38 f(i,1,n) 39 { 40 scan(a[i]); 41 a[i+n]=a[i];//环状变为链状 42 } 43 f(i,1,n) 44 { 45 ans=max(ans,dfs(i,n+i-1)); 46 } 47 pf("%d",ans); 48 }