【动态规划】[NOIP2003]加分二叉树
2017-10-29 19:58
363 查看
题目
感觉这个题挺难的啊 毕竟dp很弱
一个比较经典的树形dp
我们用f[i][j]表示区间i~j的最大加分 dp[i][j]表示区间i~j的最大加分时的根节点是什么 所以初始化f[i][i] = a[i] dp[i][i] = i
然后就是循环枚举区间 然后在每个区间中在枚举根节点 如果发现当前区间的左子树的加分×右子树的加分 + 根的分数大于当前的f[i][j]就更新
最后还要输出一个前序遍历 也就是头左右 深搜一下即可
代码如下
感觉这个题挺难的啊 毕竟dp很弱
一个比较经典的树形dp
我们用f[i][j]表示区间i~j的最大加分 dp[i][j]表示区间i~j的最大加分时的根节点是什么 所以初始化f[i][i] = a[i] dp[i][i] = i
然后就是循环枚举区间 然后在每个区间中在枚举根节点 如果发现当前区间的左子树的加分×右子树的加分 + 根的分数大于当前的f[i][j]就更新
最后还要输出一个前序遍历 也就是头左右 深搜一下即可
代码如下
#include<iostream> #include<cstdio> #include<cctype> using namespace std; #define in = read() typedef long long ll; typedef unsigned int ui; const ll size = 100 + 1; int n , l , r; int a[size] , f[size][size] , dp[size][size]; inline ll read(){ ll num = 0 , f = 1; char ch = getchar(); while(!isdigit(ch)){ if(ch == '-') f = -1; ch = getchar(); } while(isdigit(ch)){ num = num*10 + ch - '0'; ch = getchar(); } return num*f; } void dfs(int x , int y){ printf("%d " , dp[x][y]); if(dp[x][y] > x) dfs(x , dp[x][y] - 1); if(dp[x][y] < y) dfs(dp[x][y] + 1 , y); } int main(){ n in; for(register int i=1;i<=n;i++){ a[i] in; f[i][i] = a[i]; dp[i][i] = i; } int j; for(register int u=2;u<=n;u++) for(register int i=1;i+u-1<=n;i++){ j = i + u - 1; for(register int k=i;k<=j;k++){ l = f[i][k - 1]; r = f[k + 1][j]; if(k == i && k != j) l = 1; if(k == j && k != i) r = 1; if(f[i][j] < l*r + f[k][k]){ dp[i][j] = k; f[i][j] = l*r + f[k][k]; } } } printf("%d\n" , f[1] ); dfs(1 , n); return 0; } //COYG
相关文章推荐
- 【原题】【noip 2003 T2】【动态规划】加分二叉树
- [NOIP2003]加分二叉树【动态规划】
- NOIP2003-加分二叉树-dp-区间型动态规划
- CJOJ 1010【NOIP2003】加分二叉树 / Luogu 1040 加分二叉树(树型动态规划)
- [NOIP2003]加分二叉树 --动态规划-类似矩阵相乘
- NOIP-2003 加分二叉树
- [NOIP2003]加分二叉树
- CJOJ 1010【NOIP2003】加分二叉树 / Luogu 1040 加分二叉树 /CodeVS 1090 加分二叉树
- NOIP2003 洛谷1040 加分二叉树
- 题目:[NOIP2003]加分二叉树
- 【NOIP2003提高组】加分二叉树
- NOIP 2003 加分二叉树
- 【树形DP】[NOIP2003]加分二叉树
- noip2003加分二叉树
- noip2003 加分二叉树 (树形dp+分治法,已知中序,输出前序)
- Noip 2003 加分二叉树 - 区间DP
- [noip2003]加分二叉树
- noip2003提高组之加分二叉树
- NOIP2003 加分二叉树
- [NOIP2003]加分二叉树