第十三周小结

  这周可真是大起大落,情况不断变化,突然来的放假打乱了学习的进度,欣慰的是最终还是回到了家里,几日来紧绷的心情也缓解了。这周没看新的知识,只是看了几道树形dp的题目。

二叉苹果树
题意:一棵二叉苹果树,有N个结点,编号为1-N,树根编号为1。用一根树枝两端连接的结点的编号来描述一根树枝的位置。一些树枝上长有苹果,现对树进行剪枝操作。给定保留的树枝数量,求出最多能留住多少苹果。

题解:因为题目数据量不大,这次用邻接矩阵来写。设w[x][y]为边的值,因为树是双向的,同时记录w[y][x]。设tree[v,1]为节点v的左子树,tree[v,2]为节点v的右子树,然后递归建树。下一步找状态转移方程,设f[i][j]表示以i为节点的根保留k条边的最大值,则分析可得,f[v][k]=max(f[v][k],(f[tree[v][1]][i]+f[tree[v][2]][k-i-1]+num[v]))。最后求得f[1][Q+1]即为答案。

#include<bits/stdc++.h>
using namespace std;
const int x=105;
int n,q;
int tree[x][5]={0},w[x][x]={0},num[x]={0},f[x][x]={0};
void build(int x,int y,int z);
void settree(int v)
{  int k=0;
    for(int i=0;i<=n;i++)
        if(w[v][i]>=0)
        {   k++;
            build(v,i,k);
            if(k==2) return;
        }
}
void build(int x,int y,int z)
{
    num[y]=w[x][y];
    tree[x][z]=y;
    w[x][y]=-1;w[y][x]=-1;
    settree(y);
}
void dfs(int v,int k)
{   if(k==0)    f[v][k]=0;
    else if(tree[v][1]==0 && tree[v][2]==0) f[v][k]=num[v];
    else
    {   f[v][k]=0;
        for(int i=0;i<k;i++)
        {  if(f[tree[v][1]][i]==0)    dfs(tree[v][1],i);
           if(f[tree[v][2]][k-i-1]==0)    dfs(tree[v][2],k-i-1);
           f[v][k]=max(f[v][k],(f[tree[v][1]][i]+f[tree[v][2]][k-i-1]+num[v]));
        }
    }
}
int main()
{   cin>>n>>q;
    for(int i=0;i<=n;i++)
        for(int j=0;j<=n;j++)
        {  w[i][j]=-1;
           w[j][i]=-1;
        }
    for(int i=0;i<n;i++)
    {   int x,y,z;
        cin>>x>>y>>z;
        w[x][y]=z;
        w[y][x]=z;
    }
    settree(1);
    dfs(1,q+1);
    cout<<f[1][q+1]<<endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值