uva 11782 - Optimal Cut (树形dp)

该博客介绍了如何找到加权二叉树中最大权重的切口(Optimal Cut),其中切口包含的节点数不超过K个。博主分享了首次尝试使用树形动态规划(DP)解决此类问题的代码实现。
摘要由CSDN通过智能技术生成

  Optimal Cut 

cut of a binary tree is a set of tree nodes such as for each possible path from the root node to any leaf node, just one node in the cut belongs to the path. In a weighted binary tree, one can compute a weightedcut, because it would include weighted nodes. The total weight of such cut can be computed by adding up the weights of the nodes in it. The figure below shows a weighted binary tree. The gray nodes represent a weighted cut, and its total weight is 14.

\epsfbox{p11782.eps}

Now, given a weighted binary tree, you have to write a program that finds the weighted cut with the maximal total weight value among all possible weighted cuts in the tree. This is hereafter called the Optimal Cut of the input binary tree. However, to make it a bit more interesting, your program must find the optimal cut that includes no more than K nodes, and report its weight. In the figure above, for instance, the nodes of the optimal cut sums 28 when K = 3, and 15 when K = 2.

Input 

The input can contain several problems. Each problem contains the description of a complete binary tree in a single line. This description corresponds to sequence of integer numbers, separated of each other by a blank space. The description starts with an integer  0$ \le$H < 20  representing the height of the tree, followed by another integer  1$ \le$K$ \le$20  representing the maximum number of nodes in the optimal cut to be found. Then, the weights  -103$ \le$Wi$ \le$103  of the nodes follow, listed in pre-order. The end of input is indicated by a single line containing only an integer value of ` -1 '.

Output 

For each problem in the input, the output should be a single line with a single integer number, representing the total weight of the optimal cut found.

Sample Input 

2 3 8 6 7 -2 -1 2 1
0 1 1
3 3 -8 1 0 0 1 2 1 1 -1 1 1 1 3 1 4
-1

Sample Output 

9
1
5

第一次写树形dp,还是贴一发代码吧。

//11782
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <iostream>
#include <stack>
#include <set>
#include <cstring>
#include <stdlib.h>
#include <cmath>
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = (1<<20) + 5;
const int maxk = 20 + 5;
const int INF = 2000000000;

int val[maxn];
int n;

void read(int x, int d){
    if(d > n) return;
    scanf("%d", &val[x]);
    read(2*x+1, d+1);
    read(2*x+2, d+1);
}

int dp[maxn][maxk];

int dfs(int x, int k, int d){
    if(d > n) return -INF;
    if(dp[x][k] != -INF) return dp[x][k];
    if(k == 1){
        return dp[x][k] = val[x];
    }

    dp[x][k] = dfs(x, k-1, d);
    for(int j = 1;j < k;j++){
        int teml = dfs(2*x+1, j, d+1);
        int temr = dfs(2*x+2, k-j, d+1);
        if(teml != -INF && temr != -INF)
            dp[x][k] = max(dp[x][k], teml+temr);
    }
    return dp[x][k];
}

int main(){
    int k;
    while(scanf("%d", &n)){
        if(n == -1) break;
        scanf("%d", &k);
        read(0, 0);

        for(int i = 0;i < (1<<(n+1));i++){
            for(int j = 0;j < maxk;j++){
                dp[i][j] = -INF;
            }
        }
        int ans = dfs(0, k, 0);
        printf("%d\n", ans);

    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值