bzoj 1017 tree dp
这道题几经波折啊。
最开始和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的更多相关文章
- bzoj 2212 Tree Rotations
bzoj 2212 Tree Rotations 考虑一个子树 \(x\) 的左右儿子分别为 \(ls,rs\) .那么子树 \(x\) 内的逆序对数就是 \(ls\) 内的逆序对数,\(rs\) 内 ...
- 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 ...
- HDU 4359——Easy Tree DP?——————【dp+组合计数】
Easy Tree DP? Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)To ...
- TYOI Day1 travel:Tree dp【处理重复走边】
题意: 给你一棵树,n个节点,每条边有长度. 然后有q组询问(u,k),每次问你:从节点u出发,走到某个节点的距离mod k的最大值. 题解: 对于无根树上的dp,一般都是先转成以1为根的有根树,然后 ...
- HDU 4359 Easy Tree DP?
Easy Tree DP? Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)To ...
- bzoj 1017: [JSOI2008]魔兽地图DotR【树形dp+背包】
bzoj上是一个森林啊--? dp还是太弱了 设f[i][j][k]为到点i,合成j个i并且花费k金币能获得的最大力量值,a[i]为数量上限,b[i]为价格,p[i]为装备力量值 其实这个状态设计出来 ...
- BZOJ 1017 魔兽地图DotR(树形DP)
题意:有两类装备,高级装备A和基础装备B.现在有m的钱.每种B有一个单价和可以购买的数量上限.每个Ai可以由Ci种其他物品合成,给出Ci种其他物品每种需要的数量.每个装备有一个贡献值.求最大的贡献值. ...
- BZOJ.1017.[JSOI2008]魔兽地图(树形DP 背包DP)
题目链接 树形DP,考虑子节点对父节点的贡献. 设f[x][i][j]表示当前为x,用i个x去合成上一层装备,花费为j的最大价值. 由子节点转移时 是一个分组背包,需要一个辅助数组g[i][j]表示前 ...
- 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 ...
随机推荐
- java中的matches -> 完全匹配
matches是完全匹配.跟matcher不一样, matcher像perl正则, 能匹配到符合的都会返回true, 而这个matches要完全一模一样才行. import java.util.reg ...
- Linux下搜索命令
linux下用于查找文件的5个命令,有需要的朋友可以参考下.包括find,whereis,locate,which与type. linux下用于查找文件的5个命令,有需要的朋友可以参考下.包括find ...
- Linux中fork()函数的底层实现【转】
转自:http://blog.csdn.net/duoru_xiong/article/details/76358812 1. fork(),vfork(),clone()的区别 这三个系统调用的底层 ...
- php判断是手机还是pc访问从而走不同url
<?php header("Content-type:text/html;charset=utf-8"); function is_mobile(){ $user_agent ...
- 最直白、最易懂的话带你认识和学会---数据分析基础包之numpy的使用
前言 numpy是一个很基础很底层的模块,其重要性不言而喻,可以说对于新手来说是最基础的入门必须要学习的其中之一.在很多数据分析,深度学习,机器学习亦或是人工智能领域的模块中,很多的底层都会用到这个模 ...
- OpenSSL 给自己颁发根证书,由根证书签发下级证书的步骤。
1.建立根证书 (1)生成私钥 openssl genrsa -des3 -out CAroot.key 2048.产生一个2048位的私钥,在安装的openssl目录下调用openssl命令. 需要 ...
- day5模块
模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需要多个函数才 ...
- Yii 简明学习教程
Yii是一个基于组件的高性能PHP框架,用于快速开发Web应用程序(下面内容基于Yii 1.1) 1. 典型的工作流 用户向入口脚本index.php发起请求 入口脚本加载应用配置config.php ...
- js:防抖动与节流【转载】
源文:https://blog.csdn.net/crystal6918/article/details/62236730#reply <!DOCTYPE html> <html l ...
- java 用maven 构建项目时@Override错误的解决办法
把工程编译时使用JDK1.6以上版本可以解决. eclipse中 Preferences-->Java-->Compiler-->Configure Project Specific ...