陕西省集训之树形dp
来源:互联网 发布:mysql 主从备份 主键 编辑:程序博客网 时间:2024/04/27 19:13
doc老师给的树形dp的建议是一次dfs出来所有的解,而不是用记忆化搜索,每次都去dfs子解然后看是否算过了
A题:
http://poj.org/problem?id=2342
There is going to be a party to celebrate the 80-th Anniversary of the Ural State University. The University has a hierarchical structure of employees. It means that the supervisor relation forms a tree rooted at the rector V. E. Tretyakov. In order to make the party funny for every one, the rector does not want both an employee and his or her immediate supervisor to be present. The personnel office has evaluated conviviality of each employee, so everyone has some number (rating) attached to him or her. Your task is to make a list of guests with the maximal possible sum of guests’ conviviality ratings.
每个员工参加晚会都有一个欢乐值,但是不能和自己直属上司同时去
#include <iostream>#include <cstdio>const int maxn = 6050;int n;int happy[maxn],fa[maxn];bool book[maxn];int dp[maxn][3];using namespace std;int Rt;void init(){ int L,K; cin >> n; for(int i = 1; i <= n ;i++) scanf("%d",&happy[i]); while(1){ scanf("%d%d",&L,&K); if(L == 0 && K == 0) break; fa[L] = K; book[L] = true; } for(int i = 1 ; i <= n;i++) if(book[i] == false) Rt = i; //找根节点}void dfs(int root) //第二维1是选择,0是不选{ if(dp[root][1] != 0||dp[root][0] != 0) return; for(int i = 1; i <= n ;i++) if(fa[i] == root) dfs(i); for(int i = 1; i <= n ;i++){ if(fa[i] == root){ dp[root][1] += dp[i][0]; dp[root][0] += max(dp[i][1],dp[i][0]); } } dp[root][1] += happy[root];}int main(){ init(); dfs(Rt); cout << max(dp[Rt][0],dp[Rt][1]); return 0;}
b题:
http://poj.org/problem?id=2486
Wshxzt is a lovely girl. She likes apple very much. One day HX takes her to an apple tree. There are N nodes in the tree. Each node has an amount of apples. Wshxzt starts her happy trip at one node. She can eat up all the apples in the nodes she reaches. HX is a kind guy. He knows that eating too many can make the lovely girl become fat. So he doesn’t allow Wshxzt to go more than K steps in the tree. It costs one step when she goes from one node to another adjacent node. Wshxzt likes apple very much. So she wants to eat as many as she can. Can you tell how many apples she can eat in at most K steps.
#include <iostream>#include <cstdio>#include <vector>#include <algorithm>using namespace std;int N,K;const int maxn = 210; // ????vector<int> ve[maxn];int apple[maxn];int dp1[maxn][maxn][maxn];//dp1[i][j][k] : 第i个节点的儿子共一共j条边k个节点已经考虑,且回到这个节点int dp2[maxn][maxn][maxn];//dp2[i][j] :第i个节点的儿子共一共j条边,且不回到这个节点int Deg[maxn] ;void init(){ for(int i =1; i <= N ;i++) { scanf("%d",&apple[i]); ve[i].clear(); } for(int j = 1; j < N; j++){ int u,v; scanf("%d%d",&u,&v); ve[u].push_back(v); ve[v].push_back(u); }}void dfs(int fa , int x){ Deg[x] = 0; for(int i = 0 ; i < ve[x].size();i++){ if(ve[x][i]!=fa) { dfs(x,ve[x][i]); Deg[x] ++; } } //返回来 dp1[x][0][0] = apple[x] ; int i = 0 ; for (int e = 0 ; e < ve[x].size() ; e ++ ) if (ve[x][e] != fa) { // i表示前i个子节点 int y = ve[x][e]; i ++ ; //cerr << "i=" << i << "\n" ; for(int j = 0;j<=K;j++){//给所有儿子节点j条边 dp1[x][j][i] = dp1[x][j][i-1] ;//不要i个节点时 for(int k = 0 ; k <= j;k++){ //给当前儿子节点k条边 if (j-k-2>=0 && dp1[y][k][Deg[y]] + dp1[x][j-k-2][i-1] > dp1[x][j][i] ) {//选择第i个点,前面所有点获得j-k-2条 dp1[x][j][i] = dp1[y][k][Deg[y]] + dp1[x][j-k-2][i-1]; } } } } //dp2[x][0][0] = apple[x]; // cout << "x = "<<dp2[x][0][0] <<endl; i = 0; for(int e = 0 ;e < ve[x].size();e++) if(ve[x][e] != fa){ int y = ve[x][e]; i++; for(int j = 0 ; j <= K ;j++){ dp2[x][j][i] = dp2[x][j][i-1]; for(int k = 0 ; k<= j ;k++){ if(j-k-1>=0){ dp2[x][j][i] =max( dp2[y][k][Deg[y]]+dp1[x][j-k-1][i-1] , dp2[x][j][i]); dp2[x][j][i] =max( dp1[y][k][Deg[y]]+dp1[x][j-k-1][i-1] , dp2[x][j][i]); // if(x == 2 && j == 3 && i ==3) cout << "dp1[" << y <<"][" <<k <<"][" << Deg[y] <<"] = " <<dp1[y][k][Deg[y]] <<"; dp1["<< x <<"][" <<j-k-1 <<"][" <<i-1 <<"] = " <<dp1[x][j-k-1][i-1] <<"\n"; if(j-k-2 >= 0) dp2[x][j][i] = max(dp2[x][j][i], dp1[y][k][Deg[y]]+dp2[x][j-k-2][i-1]); } } } }}int main(){ while(cin >> N>>K){ init(); dfs(-1,1); int ans = 0; for(int i = 0 ; i <= K ;i++){ ans = max(ans,dp1[1][i][Deg[1]]); ans = max(ans,dp2[1][i][Deg[1]]); } cout << ans<<endl; } return 0;}
- 陕西省集训之树形dp
- 陕西省集训(数位dp)
- 陕西省集训之树状数组
- 集训-可割点(树形DP)
- 陕西省集训(单调队列)
- 集训-蚂蚁聚会(树形DP)
- 集训-vijos选课(树形DP)
- 集训-移动信号(树形DP)
- 集训-打怪兽(树形DP)
- 2017暑期集训Day 14 树形dp
- 【暑假集训】之被ACM金牌大神虐的第三天之树形dp篇
- 陕西省集训day1(枚举,贪心,二分)
- 陕西省集训day3(搜索上)
- 陕西省集训 day4(搜索下)
- 陕西省集训(并查集)
- hdu4714之树形DP
- hdu1561之树形dp
- poj1155之树形DP
- office 2010激活
- 使用SparkSQL内置函数接口开发StructType/Row转Json函数
- java 操作mysql的创建数据库及数据的增删改查
- Mongodb的update操作
- android view的setVisibility方法值
- 陕西省集训之树形dp
- 数据库性能优化
- 利用VS2012自带功能,将xml文档反序列化为对象
- Oracle 唯一主键引发的行锁
- 纯C语言 四则计算
- 灰度图像的8位平面分解
- HQL语句--where(限制)
- 字节对齐的问题
- 【6】C++命名约定