zoukankan      html  css  js  c++  java
  • 洛谷 2015 二叉苹果树

          原题链接:https://www.luogu.org/problem/P2015

          题意就是给你n-1条树枝,每条树枝上都带有一定的苹果,问最后留下m根树枝,能拥有的苹果的最大值,根节点为1,每个节点只有2种情况,有2个儿子,或没有儿子。

          这题是一个很典型的树形结构,因为节点以边相连,又为二叉结构,无环。我们这时候从根节点下顺,找到最深的儿子,然后一步步开始回溯,以当前回溯到的这个点作为根,考虑他

    有几条边的最大值。那从下至上递推回去,根节点的状态只与2个子节点有关,很明显,这就是一个dp,且是树形的。

          本题的状态转移方程要先列出:dp[i][j]=max{ dp[i][j],dp[i][j-k-1]+dp[son[i]][k]+val[i][son[i]] }(0<=j<=m,0<=k<j).接下来解释这个方程从何而来。

        

         以样例为例,我们这时候从根节点1向下搜索,找到了2,可是2这时候作为单点,并不存在边,便回溯,到3,这时候3-2有一条边,我们可以考虑是否要添这条边,dp[3][1]这时候要由dp[2][0]

    转移而来,为什么呢,因为这时候3如果要与2相连,是肯定要加3-2这条边,不然子树与根就无法连接起来了吧。接下来查到5这个点回溯,可以处理dp[3][2]了,dp[3][2]只由dp[5][0]和dp[5][1]而来,

    因为3-2处理过了对吧,由dp[5][1]而来的时候,为什么加的是dp[3][0]呢?(请注意观察式子,可以用笔推导),因为前面有提到过,若要根与子树相连,必须选取根与子树的根的边。所以整个式子

    就很好理解,你当前的这个点的儿子取j条边,你的根就只能取m-j-1条边。

         代码实现如下:

        

    #include<iostream>
    #include<vector>
    #include<cstring>
    using namespace std;
    int dp[105][105];
    vector<int>son[105];
    int val[105][105];
    int vis[105];
    int n,m;
    void dfs(int x)
    {
        int len=son[x].size();
        vis[x]=1;///经过的点打上标记,不再处理
        for(int i=0;i<len;i++)
        {
            int y=son[x][i];
            if(vis[y]==1)
            {
                continue;
            }
            vis[y]=1;///谁先到谁是爹
            dfs(y);
            for(int j=m;j>=1;j--)
            {
                for(int k=j-1;k>=0;k--)
                {
                    dp[x][j]=max(dp[x][j],val[x][y]+dp[y][k]+dp[x][j-k-1]);///文中解释
                }
            }
        }
    }
    int main()
    {
        cin>>n>>m;
        memset(vis,0,sizeof(vis));
        for(int i=1;i<n;i++)
        {
            int u,v,w;
            cin>>u>>v>>w;
            son[u].push_back(v);
            son[v].push_back(u);
            ///这里建双向边,主要是不知道哪个是父亲,所以添加双向边。
            val[u][v]=w;
            val[v][u]=w;
            ///这里我与网上的做法不同,他们喜欢把值赋予节点上,那样子不好理解,这样的赋值可以直观看出他就是边权
        }
        dfs(1);///从根节点开始
        cout<<dp[1][m]<<endl;///回溯至最开始的根节点,m条边的最大值
    }
  • 相关阅读:
    Open source cryptocurrency exchange
    Salted Password Hashing
    95. Unique Binary Search Trees II
    714. Best Time to Buy and Sell Stock with Transaction Fee
    680. Valid Palindrome II
    Java compiler level does not match the version of the installed Java project facet.
    eclipse自动编译
    Exception in thread "main" java.lang.StackOverflowError(栈溢出)
    博客背景美化——动态雪花飘落
    java九九乘法表
  • 原文地址:https://www.cnblogs.com/NVIDIA/p/11409668.html
Copyright © 2011-2022 走看看