能量项链

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;
}
posted @ 2019-11-11 17:58  fbz  阅读(146)  评论(0编辑  收藏  举报