您的位置:首页 > 其它

VJP1100 加分二叉树(树形DP)

2013-08-24 23:54 369 查看
链接

归属树形DP 做着更像记忆化

DP很好做 就是那个输出路径恶心了。。改代码 从60多行改到120多行。。dp从1维加到三维。。

先类似记忆化搜索整棵树 枚举以i为根节点的最大值 子树类似

求完最大值 再递归搜一下前序 这题不记忆化会超时

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stdlib.h>
using namespace std;
#define LL long long
LL dp[35][35][35],a[35];
int n,path[35],to;
LL dfs(int root,int l,int r)
{
if(dp[root][l][r])
return dp[root][l][r];
if(l==r)
return dp[root][l][r] = a[l];
int i,j;
LL tt =0;
if(l==root)
{
for(i = root+1 ; i <= r ; i++)
tt = max(tt,dfs(i,root+1,r)+a[root]);
}
else if(r==root)
{
for(i = l ; i < root ; i++)
tt = max(tt,dfs(i,l,root-1)+a[root]);
}
else
{
for(i = l; i < root ; i++)
for(j = root+1 ; j <= r; j++)
{
LL s1 = dfs(i,l,root-1);
LL s2 = dfs(j,root+1,r);
tt = max(tt,s1*s2+a[root]);
}
}
return dp[root][l][r]=tt;
}
void find(int u,int l,int r,int v)
{
int i,j,x1,x2;
if(l==r)
return ;
int f = 0;
if(u==l)
{
for(i = u+1 ; i <= r ; i++)
if(dp[i][u+1][r]+a[u]==dp[u][l][r])
{
x1 = i;
break;
}
path[v+1] = x1;
find(x1,u+1,r,v+1);
}
else if(u==r)
{
for(i = l ; i < u ; i++)
if(dp[i][l][u-1]+a[u]==dp[u][l][r])
{
x1 = i;
break;
}
path[v+1] = x1;
find(x1,l,u-1,v+1);
}
else
{
for(i = l; i < u ; i++)
{
for(j = u+1; j <= r ;j++)
if(dp[i][l][u-1]*dp[j][u+1][r]+a[u]==dp[u][l][r])
{
x1 = i;
x2 = j;
f = 1;
break;
}
if(f) break;
}
path[v+1] = x1;
path[v+1+u-l] = x2;
find(x1,l,u-1,v+1);
find(x2,u+1,r,v+1+u-l);
}
}
int main()
{
int i;
cin>>n;
for(i = 1; i <= n ; i++)
cin>>a[i];
LL ans = 0;
for(i = 1; i <= n ; i++)
{
LL s = dfs(i,1,n);
if(s>ans)
{
ans =s;
path[1] = i;
}
}
cout<<ans<<endl;
find(path[1],1,n,1);
for(i = 1; i < n ; i++)
cout<<path[i]<<" ";
cout<<path
<<endl;
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: