能量项链 P1063(Luogu)

题目Luogu或者题目AcWing
一道区间\(DP\),设计状态\(f[i][j]\)表示合并\(i\to j\)的最大价值,那么合并\(i,j\)的最大价值应该是从某个最后一步转移过来,也就是某一步合并\(i,j\)的转移过来,所以枚举这个\(k\),就可以转移了。

需要注意的几个细节就是

  1. 环形要加倍,就可以变成链问题,为什么可行?考虑一个环,\(n\)个点间有\(n\)个空隙,每次通过一个空隙合并,都会少一堆,于是如果\(n\)个空隙都合并了,应该是\(0\)堆,所以不可能,所以有一个空隙一定没有使用,即 最优方案一定可以把环从某处拆开,拆开的这里不会有贡献,于是可以拆成\(n\)个开头的链。
  2. 注意初始化的时候,一个项链是没有能量的,\(f[i][i]=0\),还有就是注意给出的是头部,最后一个的尾部应该是第一个的头部,这个特殊设置一下就行。
  3. 因为环形加倍了,所以数组要两倍,否则\(\mathcal{RE}\)警告

\(\mathcal{CODE:}\)

#include <bits/stdc++.h>
using namespace std;
const int N = 208;
int n;
int a[N];
int f[N][N];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]),a[n+i]=a[i];
	a[2*n+1]=a[1];
	for(int len=2;len<=n;len++){
		for(int l=1;l+len-1<=2*n;l++){
			int r=l+len-1;
			for(int k=l;k<r;k++){
				f[l][r]=max(f[l][r],f[l][k]+f[k+1][r]+a[l]*a[k+1]*a[r+1]);
			}
		}
	}

	int res=0;
	for(int i=1;i<=n;i++)res=max(res,f[i][i+n-1]);
	printf("%d\n",res);
	return 0;
}
posted @ 2020-11-04 22:03  Z_char  阅读(132)  评论(0编辑  收藏  举报