题目:分离与合体
思路:
f[i][j]
f
[
i
]
[
j
]
表示区间
[i,j]
[
i
,
j
]
中可获得的最大价值。
转移方程:
f[i][j]=(a[i]+a[j])∗a[k]+f[i][k]+f[k+1][j]
f
[
i
]
[
j
]
=
(
a
[
i
]
+
a
[
j
]
)
∗
a
[
k
]
+
f
[
i
]
[
k
]
+
f
[
k
+
1
]
[
j
]
,其中
k∈[i,j)
k
∈
[
i
,
j
)
。
注意输出格式。
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 300
#define inf (1<<30)
int n;
int a[maxn+5];
int f[maxn+5][maxn+5]={0};
int fa[maxn+5][maxn+5]={0};
vector<int> ans;
int s;
struct Node{
int x,y,z;
Node(){}
Node(int xx,int yy,int zz) {
x=xx,y=yy,z=zz;
}
};
void readin() {
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
}
}
int dp() {
for(int i=n;i>=1;i--) {
for(int j=i;j<=n;j++) {
if(i==j) f[i][j]=a[i];
else {
for(int k=i;k<j;k++) {
if((a[i]+a[j])*a[k]+f[i][k]+f[k+1][j]>f[i][j]) {
f[i][j]=(a[i]+a[j])*a[k]+f[i][k]+f[k+1][j];
fa[i][j]=k;
}
}
}
}
}
for(int i=1;i<=n;i++) {
f[1][n]-=a[i];
}
printf("%d\n",f[1][n]);
}
void print() {
queue<Node> que;
que.push(Node(1,n,fa[1][n]));
while(!que.empty()) {
Node x=que.front();
que.pop();
printf("%d ",x.z);
Node y=Node(x.x,x.z,fa[x.x][x.z]);
Node z=Node(x.z+1,x.y,fa[x.z+1][x.y]);
if(y.z) que.push(y);
if(z.z) que.push(z);
}
}
int main() {
readin();
dp();
print();
return 0;
}