区间DP,如果不考虑算法之间的转化,那么就是很简单的,只是边界不好处理,但用记忆化搜索就不存在这样的问题了
方程: f [ l ] [ r ] = m a x ( f [ l ] [ r ] , f [ l + k ] + f [ k + 1 ] [ r ] + h e a d [ l ] ∗ h e a d [ k + 1 ] ∗ h e a d [ r + 1 ] f[l][r]=max(f[l][r],f[l+k]+f[k+1][r]+head[l]*head[k+1]*head[r+1] f[l][r]=max(f[l][r],f[l+k]+f[k+1][r]+head[l]∗head[k+1]∗head[r+1]
(head[k]是k的头标记)
代码:
#include<bits/stdc++.h>
using namespace std;
#define loop(i,s,e) for(register int i=s;i<=e;++i)
#define anti_loop(i,s,e) for(register int i=s;i>=e;--i)
#define clean(a,n) memset(a,n,sizeof(a))
#define isdegit(a) ((a>='0'&&a<='9'))
template<typename T>void read(T &x){
x=0;char r=getchar();T neg=1;
while(!isdegit(r)){if(r=='-')neg=-1;r=getchar();}
while(isdegit(r)){x=(x<<1)+(x<<3)+r-'0';r=getchar();}
x*=neg;
}
int n;
const int maxn=100+10;
int head[maxn<<1];
int f[maxn<<1][maxn<<1];
int dfs(int l,int r){
int _res=0;
if((f[l][r]==0&&l==r)||f[l][r]){
return f[l][r];
}
loop(k,l,r-1){
_res=max(_res,dfs(l,k)+dfs(k+1,r)+head[l]*head[k+1]*head[r+1]);
}
f[l][r]=_res;
return _res;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("datain.txt","r",stdin);
#endif
clean(head,0);
clean(f,0);
read(n);
loop(i,1,n){
read(head[i]);
head[i+n]=head[i];
}
int res=0;
loop(l,1,n){
res=max(res,dfs(l,l+n-1));
}
printf("%d\n",res);
return 0;
}
方程:
f
[
l
]
[
r
]
=
m
a
x
(
f
[
l
]
[
r
o
o
t
−
1
]
∗
f
[
r
o
o
t
+
1
]
[
r
]
+
w
[
r
o
o
t
]
,
f
[
l
]
[
r
]
)
f[l][r]=max(f[l][root-1]*f[root+1][r]+w[root],f[l][r])
f[l][r]=max(f[l][root−1]∗f[root+1][r]+w[root],f[l][r])
对于前序遍历,直接记录当前区间最优情况下的根,然后输出的时候递归一下就可以了
代码:
#include<bits/stdc++.h>
using namespace std;
#define loop(i,s,e) for(register int i=s;i<=e;++i)
#define anti_loop(i,s,e) for(register int i=s;i>=e;--i)
#define clean(a,n) memset(a,n,sizeof(a))
#define isdegit(a) ((a>='0'&&a<='9'))
template<typename T>void read(T &x){
x=0;char r=getchar();T neg=1;
while(!isdegit(r)){if(r=='-')neg=-1;r=getchar();}
while(isdegit(r)){x=(x<<1)+(x<<3)+r-'0';r=getchar();}
x*=neg;
}
int n;
const int maxn=50;
int w[maxn];
int f[maxn][maxn];
int broot[maxn][maxn];
int dfs(int l,int r){
int res=0;
if(f[l][r]){
return f[l][r];
}
else if(r-l<=1){
res=w[l]+w[r];
broot[l][r]=l;
}
loop(root,l+1,r-1){
int rankl=dfs(l,root-1);
int rankr=dfs(root+1,r);
if(rankl*rankr+w[root]>res){
broot[l][r]=root;
res=rankl*rankr+w[root];
}
}
f[l][r]=res;
return f[l][r];
}
void dfs2(int l,int r){
if(broot[l][r]==-1){
return;
}
printf("%d ",broot[l][r]);
dfs2(l,broot[l][r]-1);
dfs2(broot[l][r]+1,r);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("datain.txt","r",stdin);
#endif
read(n);
clean(w,0);
clean(f,0);
clean(broot,-1);
loop(i,1,n){
read(w[i]);
f[i][i]=w[i];
broot[i][i]=i;
}
printf("%d\n",dfs(1,n));
dfs2(1,n);
return 0;
}