题目大意:给出一个树,每个节点有一个值,问从1开始走走k步最多能遍历到最大的值的和;
dp[i][j][k] 当i为零是表示如果从j点开始遍历以j为跟的子树,走k步后回到原点的最大值。
dp[i][j][k] 当i为零是表示如果从j点开始遍历以j为跟的子树,走k步后不回到原点的最大值。

我们知道的是如果能走k步最大值为maxa那么走j>k步至少为maxa,所以每次用子树的和当前节点做背包,0+0= 0,0+1=1,1+0=1;

由于避免重复我是用了一个类似于滚动数组的东西处理的背包部分,但是我后来发现那样好蠢还不好写还费时其实将一类中的某一个放入背包中完全能将背包倒过来然后每到一格将所有的东西装进去就行了。

第一次的代码是这样的

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const int maxa = ;
const int maxn = ;
int dp[][maxa][maxa];//0表示能回到当前位置,1表示不回到
int edge[maxa][maxa];
int vv[maxa];
int num[maxa];
int n, p;
int dp1[maxa];
//#define max(a,b) a>b?a:b
void dfs(int a, int fa){
for(int i = ; i < num[a]; i++){
int k = edge[a][i];
if(k != fa){
dfs(k, a);
}
}
for(int i = ; i <= p; i++)
dp[][a][i] = dp[][a][i] = vv[a];
for(int u = ; u < num[a]; u++){
int v = edge[a][u];
if(v != fa){
for(int i = ; i <= p; i++)
dp1[i] = vv[a];
for(int i = ; i <= p; i++){
for(int k = ; k <= p; k++){
if(i + k + <= p){
dp1[i+k+] = max(dp1[i+k+], dp[][a][i]+dp[][v][k]);
}
if(i+k+ <= p)
dp1[i+k+] = max(dp1[i+k+], dp[][a][i]+dp[][v][k]);
}
}
for(int i = ; i <= p; i++){
dp[][a][i] = max(dp[][a][i], dp1[i]);
}
for(int i = ; i <= p; i++)
dp1[i] = vv[a];
for(int i = ; i <= p; i++){
for(int k = ; k <= p; k++){
if(i+k+ <= p){
dp1[i+k+] = max(dp1[i+k+],dp[][a][i]+ dp[][v][k]);
}
}
}
for(int i = ; i <= p; i++){
dp[][a][i] = max(dp[][a][i],dp1[i]);
}
}
}
}
int main(){
while(scanf("%d%d", &n, &p)!=EOF){
int a, b;
memset(num, , sizeof(num));
for(int i = ; i <= n; i++){
scanf("%d", &vv[i]);
}
for(int i = ; i < n; i++){
scanf("%d%d", &a, &b);
edge[a][num[a]++] = b;
edge[b][num[b]++] = a;
}
//memset(dp, 0, sizeof(dp));
dfs(, );
printf("%d\n", dp[][][p]);
}
}
/*
8 6
1 1 1 1 1 1 1 4
1 2
1 3
1 4
1 5
1 6
1 7
1 8
*/

改后是这样的

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const int maxa = ;
const int maxn = ;
int dp[][maxa][maxa];//0表示能回到当前位置,1表示不回到
int edge[maxa][maxa];
int vv[maxa];
int num[maxa];
int n, p;
//#define max(a,b) a>b?a:b
void dfs(int a, int fa){
for(int i = ; i < num[a]; i++){
int k = edge[a][i];
if(k != fa){
dfs(k, a);
}
}
for(int i = ; i <= p; i++)
dp[][a][i] = dp[][a][i] = vv[a];
for(int u = ; u < num[a]; u++){
int v = edge[a][u];
if(v != fa){
for(int i = p; i >= ; i--){
for(int k = ; k <= i; k++){
if(i - k- >= ){
dp[][a][i] = max(dp[][a][i], dp[][a][k]+dp[][v][i-k-]);
dp[][a][i] = max(dp[][a][i], dp[][a][k]+dp[][v][i-k-]);
}if(i - k - >= ){
dp[][a][i] = max(dp[][a][i], dp[][a][k]+dp[][v][i-k-]);
}
}
}
}
}
}
int main(){
while(scanf("%d%d", &n, &p)!=EOF){
int a, b;
memset(num, , sizeof(num));
for(int i = ; i <= n; i++){
scanf("%d", &vv[i]);
}
for(int i = ; i < n; i++){
scanf("%d%d", &a, &b);
edge[a][num[a]++] = b;
edge[b][num[b]++] = a;
}
//memset(dp, 0, sizeof(dp));
dfs(, );
printf("%d\n", max(dp[][][p], dp[][][p]));
}
}
/*
8 6
1 1 1 1 1 1 1 4
1 2
1 3
1 4
1 5
1 6
1 7
1 8
*/

poj2486的更多相关文章

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

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

  2. POJ2486 Apple Tree(树形DP)

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

  3. POJ-2486 Apple Tree (树形DP)

    题目大意:一棵点带权有根树,根节点为1.从根节点出发,走k步,求能收集的最大权值和. 题目分析:从一个点向其某棵子树出发有三种可能的情况: 1.停留在那棵子树上: 2.再回到这个点: 3.经过这个点走 ...

  4. POJ2486 - Apple Tree(树形DP)

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

  5. poj2486 Apple Tree (树形dp)

    题意:有一颗苹果树,树上的u节点上有num[u]个苹果,树根为1号节点,囧king从根开始走,没走到一个节点就把接点上的苹果吃光,问囧king在不超过k步的情况下最多吃多少个苹果. 解题思路:处理出两 ...

  6. poj2486 Apple Tree【区间dp】

    转载请注明出处,谢谢:http://www.cnblogs.com/KirisameMarisa/p/4374766.html   ---by 墨染之樱花 [题目链接]http://poj.org/p ...

  7. poj2486(树形dp)

    题目链接:http://poj.org/problem?id=2486 题意:一颗树,n个点(1-n),n-1条边,每个点上有一个权值,求从1出发,走m步,最多能遍历到的权值. 分析:非常不错的树形d ...

  8. POJ2486 Apple Tree

    Time Limit: 1000MS   Memory Limit: 65536KB   64bit IO Format: %lld & %llu Description Wshxzt is ...

  9. POJ2486 Apple Tree 【树上背包】

    一句话题意:一棵树,一共n个点,每个点上有一个权值,求从1出发,走k步,最多能遍历到的权值.可以往回走. 第一(二)道树上背包题,先是看了dalao的题解,改了一点就过样例了.然而....TLE??? ...

随机推荐

  1. memcache分布式小实例

    <?php /** * 分布式的 memcache set 实现 */ /** * 创建缓存实现memcache 添加分布式服务器 并设置权限 */ function createCache() ...

  2. How To install FFMPEG, FLVTOOL2, MP4Box on CentOS server 2015 easy method

    for i386:wget http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el6.rf.i686.rpmrpm ...

  3. 文成小盆友python-num13 整个堡垒机

    本节主要内容: 1.pymsql的使用 2.SQLAchemy使用 3.Paramiko 4.通过ORM功能使用和Paramiko的使用实现一个简单的堡垒机模型. 一.pymsql的使用 pymsql ...

  4. C语言学习笔记--指针与字符串

    字符类型 char(character)是一种整数,也是一种特殊的类型:字符.这是因为 ① 用单引号表示的字符字符字面量:‘a’,'1' ②‘’也是一个字符 ③printf和scanf里用%c来输入. ...

  5. BZOJ3396: [Usaco2009 Jan]Total flow 水流

    3396: [Usaco2009 Jan]Total flow 水流 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 45  Solved: 27[Sub ...

  6. 【转】Beaglebone Black

    原文网址:http://bbs.eeworld.com.cn/thread-431409-1-1.html 开源硬件在国外火得一塌糊涂,国内却没有那么多人玩,直接导致中文论坛资料严重缺乏……但这也挡不 ...

  7. Android豆瓣图书查询Demo

    原文出自:方杰| http://fangjie.info/?p=26 转载请注明出处 首先先看一下Demo预览效果吧,主要也就是两个Activity.涉及到的技术有zxing开源项目的使用,网络协议豆 ...

  8. 算法导论(第三版)Problems2(归并插入排序、数列逆序计算)

    讨论内容不说明,仅提供相应的程序. 2.1:归并插入排序θ(nlgn) void mergeInsertionSort(int a[], int l, int r, int k) { int m; & ...

  9. 大型分布式C++框架《四:netio之buffer管理器 下》

    每周一篇又来了.这次主要介绍netio的buffer管理器. 首先buffer管理是每一个网络层不可回避的问题.怎么高效的使用buffer是很关键的问题.这里主要介绍下我们的netio是怎么处理.说实 ...

  10. Easyui获取数据库date数据的显示

    众所周知Oracle数据库中的date与众不同,在Easyui中显示数据库的date类型如果不经过转化为显示为Object.因此需要经过处理. 1.首先你要写转化date的JavaScript < ...