poj2486
题目大意:给出一个树,每个节点有一个值,问从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的更多相关文章
- poj2486 Apple Tree (树形dp+分组背包)
题目链接:https://vjudge.net/problem/POJ-2486 题意:一棵点权树,起点在1,求最多经过m条边的最大点权和. 思路: 树形dp经典题.用3维状态,dp[u][j][0/ ...
- POJ2486 Apple Tree(树形DP)
题目大概是一棵树,每个结点都有若干个苹果,求从结点1出发最多走k步最多能得到多少个苹果. 考虑到结点可以重复走,容易想到这么个状态: dp[u][k][0]表示在以结点u为根的子树中走k步且必须返回u ...
- POJ-2486 Apple Tree (树形DP)
题目大意:一棵点带权有根树,根节点为1.从根节点出发,走k步,求能收集的最大权值和. 题目分析:从一个点向其某棵子树出发有三种可能的情况: 1.停留在那棵子树上: 2.再回到这个点: 3.经过这个点走 ...
- POJ2486 - Apple Tree(树形DP)
题目大意 给定一棵n个结点的树,每个结点上有一定数量的苹果,你可以从结点1开始走k步(从某个结点走到相邻的结点算一步),经过的结点上的苹果都可以吃掉,问你最多能够吃到多少苹果? 题解 蛋疼的问题就是可 ...
- poj2486 Apple Tree (树形dp)
题意:有一颗苹果树,树上的u节点上有num[u]个苹果,树根为1号节点,囧king从根开始走,没走到一个节点就把接点上的苹果吃光,问囧king在不超过k步的情况下最多吃多少个苹果. 解题思路:处理出两 ...
- poj2486 Apple Tree【区间dp】
转载请注明出处,谢谢:http://www.cnblogs.com/KirisameMarisa/p/4374766.html ---by 墨染之樱花 [题目链接]http://poj.org/p ...
- poj2486(树形dp)
题目链接:http://poj.org/problem?id=2486 题意:一颗树,n个点(1-n),n-1条边,每个点上有一个权值,求从1出发,走m步,最多能遍历到的权值. 分析:非常不错的树形d ...
- POJ2486 Apple Tree
Time Limit: 1000MS Memory Limit: 65536KB 64bit IO Format: %lld & %llu Description Wshxzt is ...
- POJ2486 Apple Tree 【树上背包】
一句话题意:一棵树,一共n个点,每个点上有一个权值,求从1出发,走k步,最多能遍历到的权值.可以往回走. 第一(二)道树上背包题,先是看了dalao的题解,改了一点就过样例了.然而....TLE??? ...
随机推荐
- 读书笔记 -part1
自从毕业以后到现在~看的书是越来越少了 の其实好像貌似从来没有认认真真的看书 除非工作遇到难于解决的问题迫不得已才去翻书看 有些问题也是莫名其妙的就这样解决了 于是乎被人美名其曰“高人”或&quo ...
- jdbc接口api
java.sql.* 和 javax.sql.* |- Driver接口: 表示java驱动程序接口.所有的具体的数据库厂商要来实现此接口. |- connect(url, properties): ...
- js 解析 json
1.简单的json格式 { "user": [ { "name":"name1", "age":24, "se ...
- ASP超级网店V2.5一注入漏洞
Title:ASP超级网店V2.5一注入漏洞 --2011-10-30 17:59 ASP超级网店V2.5 这个系统,有很多地方可以注入 http://www.xxxxxx.com/admin/pi ...
- 使用dom4j生成xml字符串,以及解析xml字符串
基于dom4j-1.6.1.jar import java.io.IOException; import java.io.StringWriter; import java.util.ArrayLis ...
- android ids.xml资源的使用
ids.xml文件例子: XML file saved at res/values/ids.xml: 使用方式: 一:
- android实现类似于支付宝余额快速闪动的效果
效果如下: 此图片不会动,但实际上是会快速跳动的. 之前看到有支付宝的效果非常牛逼.就是进去看到余额呼噜噜的直接上蹿下跳到具体数字,效果帅,但不知道怎么实现,最近终于知道了. 思路: 首先经常用 ...
- poj3237 Tree
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- Activity — 4 launch mode
launchMode在多个Activity跳转的过程中扮演着重要的角色,它可以决定是否生成新的Activity实例,是否重用已存在的Activity实例,是否和其他Activity实例公用一个task ...
- java中小工具————UUID
示例代码: package com.lky.test; import java.util.UUID; import org.junit.Test; /** * @Title: testUUID.jav ...