专栏文章

题解:P1063 [NOIP2006 提高组] 能量项链

P1063题解参与者 8已保存评论 11

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
11 条
当前快照
1 份
快照标识符
@miqhs8j2
此快照首次捕获于
2025/12/04 05:01
3 个月前
此快照最后确认于
2025/12/04 05:01
3 个月前
查看原文
这道题就是区间动态规划的一道超级~水~模版的一道题。与这道题几乎一模一样。
思路
  1. 区间动态规划数组定义:就简单粗暴, dpi,jdp_{i,j} 表示区间 [ij)[i,j) 中最大能量释放值。注意,区间是左闭右开
  2. 确定区间分段。没有特殊限制,时间复杂度允许。 循环 kk (区间 [i,j)[i,j) , i<k<ji<k<j )。
  3. 状态转移方程。已知区间 [i,j)[i,j) ,断点 kk 。求 dp[i][j]dp[i][j] 。 首先, dpi,kdp_{i,k}dpk,jdp_{k,j} 合并。最后再加上断点左右的区间最大能量释放值就行了,即 dpi,kdp_{i,k}dpk,jdp_{k,j} 的和。 由题意,有以下计算代码:
CPP
int yh(int m,int r,int n){
	return m*r*n;
}//r,断点。m,区间[i,j)的i。n,区间[i.j)的j。
完整代码:
CPP
#include<bits/stdc++.h>
#define int long long
#include<iostream>
#define unsigned long long ull
using namespace std;
int yh(int m,int r,int n){
	return m*r*n;
}
const int N=210;
int a[N];
int dp[N][N];
int n;
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		a[i+n]=a[i];//环形,数组按照a[1],……,a[n],a[1],……,a[n]存
	}
	n*=2;//环形,长度乘2。
	for(int len=2;len<=n;len++){//当前序列长度
		for(int i=1;i<=n-len+1;i++){//当前序列开头
			int j=i+len-1;//当前序列结尾
			for(int k=i+1;k<j;k++){//枚举断点
				dp[i][j]=max(dp[i][j],dp[i][k]+dp[k][j]+yh(a[i],a[k],a[j]));//状态转移
			}
		}
	}
	cout<<dp[1][n]/2;//n乘了2的,要除回去,或者循环在1~n,2~n+1,3~n+2……里面找最大值
	return 0;
}

评论

11 条评论,欢迎与作者交流。

正在加载评论...