这道题几经波折啊。

最开始和vfleaking一样,把题意理解错了,认为一个装备可能被多个装备依赖,然后想不出来,去看题解。

发现自己理解错了题意,自己想想,其实也不难想到dp[i][j][k]表示“i号节点代表的子树,用掉j的钱,给父亲预留k个自己(但还是父亲付钱)”的状态,写出来交上去就是T,

开始以为是常数问题,优化半天还是T,看了他人AC代码,才发现自己算法有一定问题:重复计算了很多东西。

树形动规,一般在大的树规下,每个节点还会对儿子们来一次”资源分配“,一般是用背包解决,这道题也是这样,但又有一点不一样,就是我们也要给该子树的根节点本身分配资源,

我就是这儿重复计算了,对于所有儿子的同一k,我算了多次。

 /**************************************************************
Problem: 1017
User: idy002
Language: C++
Result: Accepted
Time:16524 ms
Memory:48316 kb
****************************************************************/ #include <cstdio>
#include <cstring>
#include <vector>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define maxn 55
#define maxm 2010
#define maxl 110
#define oo 0x3f3f3f3f
using namespace std; int n, m;
int indgr[maxn];
int power[maxn], cost[maxn], limit[maxn];
int head[maxn], next[maxn], dest[maxn], wght[maxn], tot; int dp[maxn][maxm][maxl];
int ep[maxm]; void insert( int a, int b, int w ) {
tot++;
wght[tot] = w;
dest[tot] = b;
next[tot] = head[a];
head[a] = tot;
}
void dfs( int i ) {
if( !head[i] ) return;
cost[i] = ;
limit[i] = oo; for( int t=head[i]; t; t=next[t] ) {
int s = dest[t], w = wght[t];
dfs( s );
cost[i] += cost[s]*w;
limit[i] = min( limit[i], limit[s]/w );
}
} void dodp( int i ) {
if( !head[i] ) {
for( int l=; l<=limit[i]; l++ )
for( int k=l; k>=; k-- ) {
int self = (l-k);
int j = self*cost[i];
if( j>m ) break;
dp[i][j][k] = self*power[i];
}
return;
}
for( int t=head[i]; t; t=next[t] )
dodp( dest[t] );
for( int l=; l<=limit[i]; l++ ) {
for( int j=; j<=m; j++ ) ep[j]=;
for( int t=head[i]; t; t=next[t] ) {
int v = dest[t], w = wght[t];
int vl = l*w;
for( int j=m; j>=; j-- )
for( int jj=; jj<=j; jj++ )
ep[j] = max( ep[j], ep[j-jj]+dp[v][jj][vl] );
}
for( int j=; j<=m; j++ )
for( int k=l; k>=; k-- ) {
int self = l-k;
int remain = j- self*cost[i];
if( remain< ) break;
dp[i][j][k] = max( dp[i][j][k], ep[remain]+self*power[i] );
}
}
} int main() {
scanf( "%d%d", &n, &m );
for( int i=; i<=n; i++ ) {
char type[];
scanf( "%d%s", power+i, type );
if( type[]=='A' ) {
int cnt;
scanf( "%d", &cnt );
for( int t=,c,w; t<=cnt; t++ ) {
scanf( "%d%d", &c, &w );
insert( i, c, w );
indgr[c]++;
}
} else
scanf( "%d%d", cost+i, limit+i );
}
int root = ;
for( int i=; i<=n; i++ )
if( indgr[i]== ) {
root = i;
break;
}
memset( dp, , sizeof(dp) );
dfs(root);
dodp(root);
int ans = ;
for( int j=; j<=m; j++ ) ans = max( ans, dp[root][j][] );
printf( "%d\n", ans );
}

bzoj 1017 tree dp的更多相关文章

  1. bzoj 2212 Tree Rotations

    bzoj 2212 Tree Rotations 考虑一个子树 \(x\) 的左右儿子分别为 \(ls,rs\) .那么子树 \(x\) 内的逆序对数就是 \(ls\) 内的逆序对数,\(rs\) 内 ...

  2. 96. Unique Binary Search Trees (Tree; DP)

    Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For examp ...

  3. HDU 4359——Easy Tree DP?——————【dp+组合计数】

    Easy Tree DP? Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)To ...

  4. TYOI Day1 travel:Tree dp【处理重复走边】

    题意: 给你一棵树,n个节点,每条边有长度. 然后有q组询问(u,k),每次问你:从节点u出发,走到某个节点的距离mod k的最大值. 题解: 对于无根树上的dp,一般都是先转成以1为根的有根树,然后 ...

  5. HDU 4359 Easy Tree DP?

    Easy Tree DP? Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)To ...

  6. bzoj 1017: [JSOI2008]魔兽地图DotR【树形dp+背包】

    bzoj上是一个森林啊--? dp还是太弱了 设f[i][j][k]为到点i,合成j个i并且花费k金币能获得的最大力量值,a[i]为数量上限,b[i]为价格,p[i]为装备力量值 其实这个状态设计出来 ...

  7. BZOJ 1017 魔兽地图DotR(树形DP)

    题意:有两类装备,高级装备A和基础装备B.现在有m的钱.每种B有一个单价和可以购买的数量上限.每个Ai可以由Ci种其他物品合成,给出Ci种其他物品每种需要的数量.每个装备有一个贡献值.求最大的贡献值. ...

  8. BZOJ.1017.[JSOI2008]魔兽地图(树形DP 背包DP)

    题目链接 树形DP,考虑子节点对父节点的贡献. 设f[x][i][j]表示当前为x,用i个x去合成上一层装备,花费为j的最大价值. 由子节点转移时 是一个分组背包,需要一个辅助数组g[i][j]表示前 ...

  9. BZOJ 2111 [ZJOI2010]Perm 排列计数:Tree dp + Lucas定理

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2111 题意: 给定n,p,问你有多少个1到n的排列P,对于任意整数i∈[2,n]满足P[i ...

随机推荐

  1. sg函数&&子状态的讨论

    题目链接:https://cn.vjudge.net/contest/269933#problem/H 具体思路:首先,这是一个公平的比赛,并且是两个人参与,两个人都足够聪明,并且可以通过有限步结束比 ...

  2. 33 - 并发编程-线程同步-Event-lock

    目录 1 线程同步 1.1 Event 1.1.1 什么是Flag? 1.1.2 Event原理 1.1.3 吃包子 1.2 Lock 1.2.1 lock方法 1.2.2 计数器 1.2.3 非阻塞 ...

  3. linux中的计算【转】

    shell中的赋值和操作默认都是字符串处理,在此记下shell中进行数学运算的几个特殊方法,以后用到的时候可以来看,呵呵 1.错误方法举例 a) var=1+1 echo $var 输出的结果是1+1 ...

  4. 安装sudo apt-get install ros-kinetic-desktop-full,报错mv: 无法获取'/var/lib/ni/licenses.xml.dpkg-old' 的文件状态(stat): 没有。。。。

    安装sudo apt-get install ros-kinetic-desktop-full,报了一堆错误 mv: 无法获取'/var/lib/ni/licenses.xml.dpkg-old' 的 ...

  5. spring中的任务调度Quartz

    Spring 整合 Quartz 任务调度 主要有两种方式. Quartz的官网:http://www.quartz-scheduler.org/ 这两种只是一些配置文件简单配置就OK了,但是根本无法 ...

  6. redis源码分析——aofrewrite

    随着redis的运行,aof会不断膨胀(对于一个key会有多条aof日志),导致通过aof恢复数据时,耗费大量不必要的时间.redis提供的解决方案是aof rewrite.根据db的内容,对于每个k ...

  7. c++鼠标点点,获取坐标值,放入到txt文件中

    // oj3.cpp : Defines the entry point for the console application.// #include "stdafx.h"#in ...

  8. Visual Tracking with Fully Convolutional Networks

    http://blog.csdn.net/carrierlxksuper/article/details/48918297 传统的跟踪方法依赖低维的人工特征,但这种特征对目标的外观变化等问题不够鲁棒. ...

  9. Dagger:快速的依赖注入for 安卓&Java

    Dagger:快速的依赖注入for 安卓&Java 2014年5月8日 星期四 15:29 官网: http://square.github.io/dagger/ GitHub: https: ...

  10. print、println的区别

    System.out.print("a");——后面没有换行符 System.out.println("b");——后面有换行符 换行符:\r和\n以及\r\n ...