能量项链

https://loj.ac/problem/10148

题目描述

  有(n)个珠子排成一圈,每个珠子有头标记和尾标记,对于(i<n),第(i)个珠子的尾标记等于第(i+1)个珠子的头标记,第(n)个珠子的尾标记等于第(1)个珠子的头标记,每次合并时,记前一个珠子的头标记为(m),尾标记为(r),后一个珠子的尾标记为(n),那么会产生(m*r*n)的能量和一颗头标记为(m),尾标记为(n)的珠子,求合并产生的最大能量和。

思路

  依然是把环化为链做,类似的,我们用(f[i][j])表示合并(i)(j)段的珠子的能量和,那么转移方程即为(f[i][j]=max{f[i][k]+f[k+1][j]+s[i]*s[k]*s[j]}),以区间长度作为第一维即可。

代码

#include <bits/stdc++.h>
using namespace std;

int read()
{
	int res=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){res=(res<<3)+(res<<1)+(ch^48);ch=getchar();}
	return res*w;
} 

int head[220],tail[220],f[220][220];
int main() 
{
	int n=read();
	for(int i=1;i<=n;i++)
		head[i]=read(),head[i+n]=head[i];
	for(int i=1;i<n*2;i++)
		tail[i]=head[i+1];
	tail[n*2]=head[1];
	for(int len=2;len<=n;len++)
		for(int l=1;l<=n*2-len+1;l++)
		{
			int r=l+len-1;
			f[l][r]=0;
			for(int k=l;k<r;k++)
				f[l][r]=max(f[l][r],f[l][k]+f[k+1][r]+head[l]*tail[k]*tail[r]);
		}
	int ans=0;
	for(int i=1;i<=n;i++)
		ans=max(ans,f[i][i+n-1]);
	printf("%d",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/fangbozhen/p/11837202.html