ACM-11月26日周日周末训练心得

来源:互联网 发布:js charcodeat 编辑:程序博客网 时间:2024/05/22 08:20

    这周末关于树形DP的专题已经结束了,需要对这个专题进行一下总结,就我做的这些题进行一下总结。

    树形DP就是根据问题的描述,问题里的东西与树一样拥有子节点和父节点的关系,而做一些对于这些信息的检索以及寻找一些问题所需要的答案则需要寻找一些状态变化和转移。选择一些对树形DP印象比较深刻的题目进行思考。

    A这道题大致的意思是,一个公司里的职员关系就像一颗树一样存在上下级关系,一个员工可能是另一个员工的上级,要求尽可能选更多的员工,并且他们都没有上下级的关系,使得快乐值最大。这道题首先就要确定对于一个员工i来说,选择这个员工或者不选这个,所以可以有dp[i][0]为不选择i的时候最大的快乐值,dp[i][1]为选择i的时候的最大值,所以接下来的状态就是围绕i的子节点的情况进行讨论,不选择i的时候,i的下属可以选择,也可以不选择,主要还是寻找快乐值最大的方法,故有dp[i][0] += max(dp[i的下属][0], dp[i的下属][1]);选择i的时候那么所有i的下属都不能选,所以有dp[i][1]+=dp[i][0]。

    B这道题的意思是先给你每个电脑的连接关系,求的是每台电脑与最远的一个电脑的距离是多长,对于这个问题,每个电脑都可以简化为树上的一个节点,对于每一个电脑他的转移方向都有两个,一个是向他的子节点移动,一个是向他的父节点移动,这两个方向中找到最远的节点,故有dp[i][0]记录电脑i子节点的最长距离,belong[i][0]记录子节点最长路径经过的i的子节点。dp[i][0]记录电脑i子节点的第二长距离,down[i][0]记录向下第二长路径经过的i的子节点需要设置旗帜flag[i] = 0代表i的父节点的最长路径不经过i,flag[i]=1代表i的父节点的最长路径经过i。状态转移方程就是找出所有点向下的距离,然后由父向子的顺序进行遍历,设i是j的父节点如果节点j的flag[j] = 0 ,那么它的最远距离应该是dp[j][0] 和 i的最远距离+i到j的距离 中的最大值。如果节点j的flag[j] = 1 ,那么它的最远距离应该是 dp[j][0]和i的不包含j的路径的距离+i到j的距离中的最大值。这道题的不同就是用了dfs的思想并且题目有一个树形。 

    T这道题有一些非主流,这道题的树跟之前的有很大的不一样,题意大致是给出一个树的每个节点的值,然后进行一次裁边使这颗数变成两部分,求这两部分权值之差最小,这道题我一开始没有选择用树形dp,就是疯狂枚举,然后感觉会TLE,重新思考这道题用树形DP的方法,感觉这个方法还不够树形dp,看了一些别人的博客,用dp[u]来表示在u的权值之和,然后用dfs进行遍历。

void dfs(int x,int f)  {      dp[x]=a[x];      for(int i=0;i<G[x].size();i++)      {          int y=G[x][i];          if(y==f)  continue;          dfs(y,x);          dp[x]+=dp[y];      }      mini=min(abs2(2*dp[x]-sum),mini);  }
    题O印象也比较深刻,大概的意思是给定一个存在n个节点的树,从1到n去每条路耗费一定的时间,每经过一个点就可以获得这一点的权值,问如何在T时间内能到达n点并且获得的权值尽量多 。这道题的思考路程差不多是先找到最短路径的权值和最短路径上的每个点,然后由于经过每个点都需要时间,要找到时间收益最大以i为起点给他j的时间能获得的最大权值dp[i][j]。然后再算如何在最短路径上的节点分配使得最终的权值最大。dp[i][j]的意思就是从i出发并回来花费j时间所得的最大权值。状态转移方程就是dp[i][j]=dp[i的子节点1][该点分配的时间] + dp[i的子节点2][该点分配的时间] + ... + dp[i的子节点n][该点分配的时间]。

    树形DP这个专题主要还是将DFS的问题与树形的结构相结合。

原创粉丝点击