经过在机房里数日的切磁,LYD从社神牛那里学会了分离与合体,出关前,杜神牛给了他一个测试
杜神牛造了个区域,它们紧邻着排成了一行,编号1-n。在这經个区域里都放着一把OI界
的金钥匙,每一把都有一定的价值,LYD当然想得到它们了。然而杜神牛规定LYD不可以一下子
把它们全部拿走,而是每次只可以拿一把。为了尽快地拿到所有的金钥匙,LYD自然就用上了刚学的分离与合体特技。
开始LYD可以选择从 1 ~ n - 1 1~n-1 1~n-1的任何一个区域(记为K)进入,进入后LYD会在K区域发
生分离,从而分离为两个小LYD。分离完成的同时会有一面墙在k和k+1区域之间升起,从而把
的区间内任选除了区间末尾区域以外(即 1 ~ k ー 1 1~kー1 1~kー1或 k + 1 ~ n ー 1 k+1~nー1 k+1~nー1)的任何一个区域再次发生分离
就一共有了4个小小LYD…重复进行以上所叙述的分离,直到每个小LYD发现自己所在的区间只剩下了一个区域,他们就可以抱起自己梦寐以求的Oi金钥匙。
但是LYD不能就这么分成n多个个体存在于世界上,这些小LYD还会再合体,合体的两个小
LYD所在的区间中间的墙会消失。合体会获得一定的价值,计算方法是:(合并后所在区间的左右
端区域里金钥匙的价值之和)乘(之前分离的时候所在区域的金钥匙价值)
例如,LYD曾经在 1 ~ 3 1~3 1~3区间中的2号区域分离成为 1 ~ 2 1~2 1~2和3两个区间,合并时获得的价值就
是:(1号金钥匙价值+3号价值)*(2号金钥匙价值)
LYD请你编程求出最终可以获得的总价值最大是多少。并按照分离阶段从前到后,区域从左
向右的顺序,输出发生分离的区域编号
例如,先打印1分为2的分离区域,然后从左到右打印2分为4的分离区域,然后是4分为
的
注意:若有多种方案,选择分离区域尽量靠左的方案(也可以理解为输出字典序最小的)
第一行一个正整数n(2≤n≤300)
第二行为n个用空格分开的正整数,表示 1 ~ n 1~n 1~n区域里每把金钥匙的价值。
保证运算过程及结果不超出int范围
第一行的一个数,即获得的最大价值。。
第二行按照分离阶段从前到后,区域从左向右的顺序,输出发生分离的区域编号,中间用一个空格隔开,若有多种方案,选择分离区域尽量靠左的方案(也可以理解为输出字典序最小的)
7
1 2 3 4 5 6 7
238
1 2 3 4 5 6
对于 20 20% 20 的数据 , n ≤ 10 ,n≤10 ,n≤10;
对于 40 40% 40 的数据, n ≤ 50 n≤50 n≤50;
对于 100 100% 100 的数据, n , a i ≤ 300 n,ai≤300 n,ai≤300
i ≤ 300 i≤300 i≤300,保证运算过程和结果不超过 32 32 32位正整数范围。
首先这道题不难发现它就是一道裸题,首先设dp[i][j]为i~j区间的最大价值,那么不难知道dp[i][j]是由元区间dp[i][k] + dp[k + 1][r]的和加上(a[i] + a[y])*a[k],注意区间长度应该是从2开始枚举,因为1时,已经不用分裂了。
但是我们应如何输出路径呢?首先需要定义一个l[i][j],表示i~j之间最大的k点(集中转点),于是我们就只需要按顺序枚举分裂后的起始位置,结束位置即可得到最终答案,这里可以用dfs枚举,详细见代码:
void _printf(int qi, int zhong, int y) {
if(y == 0) {//如果达到目标深度则返回
return;
}
if(l[qi][zhong] == -1){//输出过就跳过
return;
}
if(flag[qi][zhong] == 0) {//如果此时的k没输出过则输出
flag[qi][zhong] = 1;
printf("%d ", l[qi][zhong]);
}
_printf(qi, l[qi][zhong], y - 1);//枚举划分点左边,这层枚举完了,深度-1
_printf(l[qi][zhong] + 1, zhong, y - 1);//枚举划分点右边
}
#include
#include
#include
#include
using namespace std;
int n, a[305], dp[305][305], l[305][305], sum = 0, flag[305][305];
void _printf(int qi, int zhong, int y) {
if(y == 0) {
return;
}
if(l[qi][zhong] == -1){
return;
}
if(flag[qi][zhong] == 0) {
flag[qi][zhong] = 1;
printf("%d ", l[qi][zhong]);
}
_printf(qi, l[qi][zhong], y - 1);
_printf(l[qi][zhong] + 1, zhong, y - 1);
}
int main() {
// freopen("separation.in", "r", stdin);
// freopen("separation.out", "w", stdout);
scanf("%d", &n);
for(int i = 1;i <= n; i++) {
scanf("%d", &a[i]);
}
memset(l, -1, sizeof(l));
for(int len = 2;len <= n; len++) {
for(int i = 1;i <= n - len + 1; i++) {
int r = i + len - 1;
for(int k = i;k < r; k++) {
if(dp[i][k] + dp[k + 1][r] + (a[i] + a[r]) * a[k] > dp[i][r]) {
dp[i][r] = dp[i][k] + dp[k + 1][r] + (a[i] + a[r]) * a[k];
l[i][r] = k;
}
}
}
}
printf("%d\n", dp[1][n]);
for(int i = 1;i <= n; i++) {
_printf(1, n, i);
}
return 0;
}