sjtu 1077 加分二叉树
2013-03-18 19:05
766 查看
树型DP入门题
题目链接:http://acm.sjtu.edu.cn/OnlineJudge/problem/1077
•设f(i,j)中序遍历为i,i+1,…,j的二叉树的最大加分,则有:
f(i,j)=max{f[i,k-1]*f[k+1,j] +d[k]}
•显然 f(i,i)=d[i]
•答案为f(1,n)
•1<=i<=k=<=j<=n
•时间复杂度 O(n3)
•要构造这个树,只需记录每次的决策值,令b(i,j)=k,表示中序遍历为i,i+1,…,j的二叉树的取最优决策时的根结点为k
最后前序遍历这个树即可。
题目链接:http://acm.sjtu.edu.cn/OnlineJudge/problem/1077
•设f(i,j)中序遍历为i,i+1,…,j的二叉树的最大加分,则有:
f(i,j)=max{f[i,k-1]*f[k+1,j] +d[k]}
•显然 f(i,i)=d[i]
•答案为f(1,n)
•1<=i<=k=<=j<=n
•时间复杂度 O(n3)
•要构造这个树,只需记录每次的决策值,令b(i,j)=k,表示中序遍历为i,i+1,…,j的二叉树的取最优决策时的根结点为k
最后前序遍历这个树即可。
/* 树型DP */ #include <cstdio> #include <cstring> #include <queue> using namespace std; #define MAX 35 #define INF 0x3f3f3f3f long long dp[MAX][MAX]; int p[MAX][MAX]; int a[MAX]; queue<int>q; long long dfs(int i ,int j) { if(i>j) return dp[i][j]=1; if(dp[i][j]!=-1) return dp[i][j]; dp[i][j]=-INF; for(int k=i; k<=j; k++) { long long t1=dfs(i,k-1); long long t2=dfs(k+1,j); if(t1*t2+a[k] > dp[i][j]) { dp[i][j]=t1*t2+a[k]; p[i][j]=k; } } return dp[i][j]; } void travel(int i ,int j) { if(i>j) return ; if(i==j) { q.push(i); return ; } int k=p[i][j]; q.push(k); travel(i,k-1); travel(k+1,j); } int main() { int n; while(scanf("%d",&n)!=EOF) { for(int i=1; i<=n; i++) scanf("%d",&a[i]); memset(p,-1,sizeof(p)); memset(dp,-1,sizeof(dp)); for(int i=1; i<=n; i++) { dp[i][i]=a[i]; p[i][i]=i; } dfs(1,n); printf("%lld\n",dp[1] ); while(!q.empty()) q.pop(); travel(1,n); printf("%d",q.front()); q.pop(); while(!q.empty()) { printf(" %d",q.front()); q.pop(); } printf("\n"); } return 0; }
相关文章推荐
- SJTU 1077 加分二叉树
- ssl1033 加分二叉树
- 南邮 OJ 1039 加分二叉树
- 【洛谷】加分二叉树,P1040
- 加分二叉树[NOIP 2003提高组][Codevs 1090]
- NOIP 2003 加分二叉树
- noip2003加分二叉树
- noip2003 加分二叉树 dp
- NOIP2003 加分二叉树
- [NOIP2003]区间dp-加分二叉树
- 1090 加分二叉树
- ·树形动规(一) 加分二叉树(洛谷p1040)
- NOIP2003-加分二叉树-dp-区间型动态规划
- 加分二叉树
- 普及练习场 深度优先搜索 加分二叉树
- VijosP1100:加分二叉树
- 【NOIP2013提高组T3】加分二叉树
- [NOIP2003]加分二叉树
- 加分二叉树_DP
- 洛谷1040 加分二叉树