题意:有一颗苹果树,树上的u节点上有num[u]个苹果,树根为1号节点,囧king从根开始走,没走到一个节点就把接点上的苹果吃光,问囧king在不超过k步的情况下最多吃多少个苹果。
解题思路:处理出两个dp数组,f1[u][i]表示在不超过i步的情况下,从u节点开始,往下吃,吃完后回到u节点,最多能吃多少苹果。f2[u][i]表示在不超过i步的情况下,从u节点开始往下吃,最多能吃多少苹果。

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std ; const int maxn = 111111 ; int max ( int a , int b ) { return a > b ? a : b ; }
int min ( int a , int b ) { return a < b ? a : b ; } struct Edge
{
int to , next ;
} edge[maxn<<1];
int head[maxn] , tot , n , m ;
int f1[111][2222] , f2[111][222] , num[maxn] , ans , dis[1111] ; void new_edge ( int a , int b )
{
edge[tot].to = b ;
edge[tot].next = head[a] ;
head[a] = tot ++ ; edge[tot].to = a ;
edge[tot].next = head[b] ;
head[b] = tot ++ ;
} int c[111][222] , d[maxn] , l ; void dfs ( int u , int fa , int *f )
{
int i , j , k ;
if ( u != 1 )
{
for ( i = dis[u] ; i <= m ; i ++ )
ans = max ( ans , f2[u][m-i] + f[i] ) ;
} int fuck[222] ;
for ( i = head[u] ; i != -1 ; i = edge[i].next )
{
int v = edge[i].to ;
if ( v == fa ) continue ; for ( j = 0 ; j <= m ; j ++ ) d[j] = 0 ;
int t = 0 ;
for ( j = head[u] ; j != -1 ; j = edge[j].next )
{
if ( edge[j].to == v || edge[j].to == fa ) continue;
t ++ ;
for ( k = 0 ; k <= m ; k ++ )
c[t][k] = f1[edge[j].to][k] ;
}
for ( j = 1 ; j <= t ; j ++ )
for ( k = m ; k >= 0 ; k -- )
for ( l = 0 ; l + 2 <= k ; l ++ )
d[k] = max ( d[k] , d[k-l-2] + c[j][l] ) ; for ( j = 0 ; j <= m ; j ++ ) fuck[j] = 0 ;
for ( j = dis[u] ; j < m ; j ++ ) fuck[j+1] = f[j] ;
for ( j = dis[u] ; j <= m ; j ++ )
for ( k = 0 ; k <= m ; k ++ )
if ( j + k + 1 <= m )
fuck[j+k+1] = max ( fuck[j+k+1] , f[j] + d[k] + num[u] ) ;
dfs ( v , u , fuck ) ;
}
} void cal ( int u , int fa )
{
int i , j , k ;
for ( i = head[u] ; i != -1 ; i = edge[i].next )
{
int v = edge[i].to ;
if ( v == fa ) continue ;
dis[v] = dis[u] + 1 ;
cal ( v , u ) ; for ( k = m ; k >= 0 ; k -- )
for ( j = 0 ; j + 2 <= k ; j ++ )
f1[u][k] = max ( f1[u][k] , f1[u][k-j-2] + f1[v][j] ) ; for ( k = 1 ; k <= m ; k ++ ) f2[u][k] = max ( f2[u][k] , f2[v][k-1] ) ; for ( j = 0 ; j <= m ; j ++ ) d[j] = 0 ;
int t = 0 ;
for ( j = head[u] ; j != -1 ; j = edge[j].next )
{
if ( edge[j].to == v || edge[j].to == fa ) continue ;
t ++ ;
for ( k = 0 ; k <= m ; k ++ )
c[t][k] = f1[edge[j].to][k] ;
} for ( j = 1 ; j <= t ; j ++ )
for ( k = m ; k >= 0 ; k -- )
for ( l = 0 ; l + 2 <= k ; l ++ )
d[k] = max ( d[k] , d[k-l-2] + c[j][l] ) ; for ( j = 0 ; j <= m ; j ++ )
for ( k = 0 ; k + 1 <= j ; k ++ )
f2[u][j] = max ( f2[u][j] , f2[v][k] + d[j-k-1] ) ;
} for ( i = 0 ; i <= m ; i ++ ) f1[u][i] += num[u] , f2[u][i] += num[u] ;
for ( i = 1 ; i <= m ; i ++ ) f1[u][i] = max ( f1[u][i] , f1[u][i-1] ) , f2[u][i] = max ( f2[u][i] , f2[u][i-1] ) ;
} void init ()
{
int i ;
memset ( head , -1 , sizeof ( head ) ) ;
memset ( f1 , 0 , sizeof ( f1 ) ) ;
memset ( f2 , 0 , sizeof ( f2 ) ) ;
memset ( dis , 0 , sizeof ( dis ) ) ;
tot = ans = 0 ;
} int f[222] ;
int main ()
{
int i , j , k , a , b ;
while ( scanf ( "%d%d" , &n , &m ) != EOF )
{
init () ;
for ( i = 1 ; i <= n ; i ++ ) scanf ( "%d" , &num[i] ) ;
for ( i = 1 ; i < n ; i ++ )
{
scanf ( "%d%d" , &a , &b ) ;
new_edge ( a , b ) ;
}
cal ( 1 , 0 ) ;
ans = f2[1][m] ;
for ( i = 0 ; i <= m ; i ++ ) f[i] = 0 ;
dfs ( 1 , 0 , f ) ;
printf ( "%d\n" , ans ) ;
}
}

poj2486 Apple Tree (树形dp)的更多相关文章

  1. POJ2486 - Apple Tree(树形DP)

    题目大意 给定一棵n个结点的树,每个结点上有一定数量的苹果,你可以从结点1开始走k步(从某个结点走到相邻的结点算一步),经过的结点上的苹果都可以吃掉,问你最多能够吃到多少苹果? 题解 蛋疼的问题就是可 ...

  2. 【POJ 2486】 Apple Tree (树形DP)

    Apple Tree Description Wshxzt is a lovely girl. She likes apple very much. One day HX takes her to a ...

  3. poj 2486 Apple Tree(树形DP 状态方程有点难想)

    Apple Tree Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9808   Accepted: 3260 Descri ...

  4. POJ 2486 Apple Tree(树形DP)

    题目链接 树形DP很弱啊,开始看题,觉得貌似挺简单的,然后发现貌似还可以往回走...然后就不知道怎么做了... 看看了题解http://www.cnblogs.com/wuyiqi/archive/2 ...

  5. URAL_1018 Binary Apple Tree 树形DP+背包

    这个题目给定一棵树,以及树的每个树枝的苹果数量,要求在保留K个树枝的情况下最多能保留多少个苹果 一看就觉得是个树形DP,然后想出 dp[i][j]来表示第i个节点保留j个树枝的最大苹果数,但是在树形过 ...

  6. Ural-1018 Binary Apple Tree(树形dp+分组背包)

    #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #i ...

  7. POJ 2486 Apple Tree (树形dp 经典题)

    #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const ...

  8. 熟练剖分(tree) 树形DP

    熟练剖分(tree) 树形DP 题目描述 题目传送门 分析 我们设\(f[i][j]\)为以\(i\)为根节点的子树中最坏时间复杂度小于等于\(j\)的概率 设\(g[i][j]\)为当前扫到的以\( ...

  9. poj2486 Apple Tree (树形dp+分组背包)

    题目链接:https://vjudge.net/problem/POJ-2486 题意:一棵点权树,起点在1,求最多经过m条边的最大点权和. 思路: 树形dp经典题.用3维状态,dp[u][j][0/ ...

  10. POJ2486 Apple Tree(树形DP)

    题目大概是一棵树,每个结点都有若干个苹果,求从结点1出发最多走k步最多能得到多少个苹果. 考虑到结点可以重复走,容易想到这么个状态: dp[u][k][0]表示在以结点u为根的子树中走k步且必须返回u ...

随机推荐

  1. jcSQL词法分析器对字符串token的解析

    上星期写完词法分析器的时候,曾遇上一个无关紧要却X疼的问题.毕竟是第一次完整地写整个语言的编译器(暂且这么叫着吧,解释器更靠谱),由于经验不足,在字符串解析这一块驻足了两天才解决掉,这里记录下来供以后 ...

  2. sql server 2008 (3)

    数据库表常用术语 关系--即二维表.每个关系都有个关系名,就是表名 域:取值范围 记录--行 字段,属性--列 关联--指哪个数据库表之间的数据彼此联系的方式 关键字:属性或属性的组合,可以唯一标识一 ...

  3. 获取Json对象的长度或计数

    最近又开始写博客了.因为最近的工作又开始与技术方面接口了.现在在开发WEB的时候,经常会遇到JSON对象的传递,JSON是个好东西,但是它却没有提供一些简单便捷的处理方法,其中获取JSON对象的长度就 ...

  4. 利用jQuery打造个性网站

    网页结构 编写全局样式(reset.css) /*全局样式*/ body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fi ...

  5. Delphi 实现无窗口移动(发WM_NCHITTEST消息计算,然后再发WM_SYSCOMMAND消息,带参数SC_DRAGMOVE)

    procedure imgListMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer) ...

  6. mysql 插入前 锁表问题

    $dbh = DBI->connect("dbi:mysql:database=$db_name;host=$ip;port=3306",$user,$passwd,{ Ra ...

  7. C语言的本质(8)——副作用与顺序点

    C 语言中,术语副作用是指对数据对象或者文件的修改.例如以下语句 var = 99; 的副作用是把 var 的值修改成 99.对表达式求值也可能产生副作用,例如: se = 100 对这个表达式求值所 ...

  8. iOS多线程总结(二)NSOperation

    NSOperation.h定义了NSOperation,内容非常的简洁,NSOperation本身是一个抽象类,定义了一个要执行的Task,NSOperationQueue是一个Task队列,当Tas ...

  9. ora-06502

    执行一个存储过程时报这个错误 ORA-06502: PL/SQL: 数字或值错误 发现是定义的字符串的缓冲区太小,赋给字符串的值又太大 修改varchar2(20)  →   varchar2(200 ...

  10. 在WPF中将某张表中的数据显示到datagrid

    a.在.xaml文件中拖入一个datagrid,然后添加列名,使用Binding="{Binding 数据库中的 列名称}",如下: <DataGrid AutoGenera ...