树型dp入门小节
来源:互联网 发布:sqlserver密码策略 编辑:程序博客网 时间:2024/06/08 03:00
做了几道树型dp的入门题,稍微总结一下
hdu1520:http://acm.hdu.edu.cn/showproblem.php?pid=1520(入门)
题意:每个人有一些活跃值,员工和上司关系组成一棵树,树上如果父亲来了,向下相邻的儿子就来不了,问最大的活跃值总和(题意略坑,可能不止一棵树)
用dp[i][0]表示当前点没来的最大值,dp[i][1]表示当前点来了的最大值,则dfs时有状态转移方程:
dp[u][0] += max(dp[v][1],dp[v][0])
dp[u][1] += dp[v][0]
其中u为父亲,v为相邻儿子,根可能有多个,枚举所有没有父亲的节点dfs就好了
#include<bits/stdc++.h>#define mem(a,b) memset(a,b,sizeof(a))#define For(a,b,c) for(int a = b;a <= c;a++)using namespace std;typedef long long ll;const int maxn = 6005;const int INF = 0x3f3f3f3f;const double eps = 1e-8;struct ppp{int v,nex;}e[maxn * 20];int tole;int N;int ru[maxn];int dp[maxn][2];int head[maxn];void make_edge(int u,int v){e[tole].v = v;e[tole].nex = head[u];head[u] = tole++;}int dfs(int u,int pre){for(int i = head[u];~i;i = e[i].nex){int v = e[i].v;if(v == pre)continue;dfs(v,u);dp[u][1] += dp[v][0];dp[u][0] += max(dp[v][0],dp[v][1]);}return max(dp[u][0],dp[u][1]);}int main(){while(~scanf("%d",&N)){if(N == 0)break;mem(head,-1);tole = 0;mem(dp,0);mem(ru,0);for(int i = 1;i <= N;i++)scanf("%d",&dp[i][1]);for(int i = 1;1;i++){int a,b;scanf("%d%d",&a,&b);if(a == 0 && b == 0)break;make_edge(b,a);make_edge(a,b);ru[a]++;}int ans = 0 ;for(int i = 1;i <= N;i++)if(!ru[i]){ans += dfs(i,-1);}cout<<ans<<endl;}}
hdu1561:http://acm.hdu.edu.cn/showproblem.php?pid=1561
题意中文,不多解释了
想法:要攻占某个城堡则其父亲节点的城堡一定要被攻占,列出状态方程为
dp[i][j],表示为第i个节点攻占了j个城堡的最大值(包括自己和儿子),那么显然对与每个节点这相当于一个背包问题
dp[u][j] = max(dp[u][j],dp[v][k] + dp[u][j - k])j从M枚举到1,k从0枚举到j(就是背包的做法),注意到0是虚构点,枚举的时候要去掉包括占领0号城堡的情况
#include<bits/stdc++.h>#define mem(a,b) memset(a,b,sizeof(a))#define For(a,b,c) for(int a = b;a <= c;a++)using namespace std;typedef long long ll;const int maxn = 202;const int INF = 0x3f3f3f3f;const double eps = 1e-8;struct ppp{ int v,nex;}e[maxn * 1000];int head[maxn],tole;void make_edge(int u,int v){ e[tole].v = v;e[tole].nex = head[u];head[u] = tole++;}int dp[maxn][maxn];int N,M;void dfs(int u,int fa){ for(int i = head[u];~i;i = e[i].nex) { int v = e[i].v; if(v == fa)continue; dfs(v,u); for(int j = M;j >= 0;j--) { int temp = j; if(u == 0) temp = j + 1; for(int k = 0;k < temp;k++) { dp[u][j] = max(dp[u][j],dp[v][k] + dp[u][j - k]); } } }}int main(){ while(scanf("%d%d",&N,&M)) { if(N == 0 && M == 0)break; mem(dp,0); tole = 0; mem(head,-1); for(int i = 1;i <= N;i++) { int a; scanf("%d%d",&a,&dp[i][1]); make_edge(i,a); make_edge(a,i); } dfs(0,-1); printf("%d\n",dp[0][M]); }
hdu1011:http://acm.hdu.edu.cn/showproblem.php?pid=1011
到下一个房间必须消灭当前房间,dp时类似背包的做法。
#include<bits/stdc++.h>#define mem(a,b) memset(a,b,sizeof(a))#define For(a,b,c) for(int a = b;a <= c;a++)using namespace std;typedef long long ll;const int maxn = 102;const int INF = 0x3f3f3f3f;const double eps = 1e-8;struct ppp{ int v,nex;}e[maxn * 1000];int head[maxn],tole;void make_edge(int u,int v){ e[tole].v = v;e[tole].nex = head[u];head[u] = tole++;}int dp[maxn][maxn];int N,M;int ori[maxn];//ori[i]为消灭玩第i个房间所需要的troopvoid dfs(int u,int fa){ for(int i = head[u];~i;i = e[i].nex) { int v = e[i].v; if(v == fa)continue; dfs(v,u); for(int k = M;k >= ori[u];k--)//要进入下一个房间这个房间必须消灭,所以k>=ori[u] for(int j = 1;j <= k - ori[u];j++)//背包做法,dp dp[u][k] = max(dp[u][k],dp[v][j] + dp[u][k - j]); }}int main(){ while(~scanf("%d%d",&N,&M)) { if(N == -1 && M == -1)break; tole= 0; mem(dp,0); mem(head,-1); for(int i = 1;i <= N;i++) { int a,b; scanf("%d%d",&a,&b); a = (a + 19) / 20; dp[i][a] = b; for(int j = a;j <= M;j++)//这个初始化一定要加 dp[i][j] = b; ori[i] = a; } for(int i = 1;i < N;i++) { int a,b; scanf("%d%d",&a,&b); make_edge(a,b); make_edge(b,a); } if(!M)//这个特判貌似必须要加....不然是WA... { printf("0\n");continue; } dfs(1,-1); int ans = -1; for(int i = 0;i <= M;i++) ans = max(dp[1][i],ans); printf("%d\n",ans); }}
0 0
- 树型dp入门小节
- 状态压缩DP 题目小节 (一)
- 状态压缩DP题目小节(二)
- 状态压缩DP题目小节(三)
- 小节
- 小节
- HDU1561 树型DP入门
- 树型DP入门
- poj 2342 树型dp入门
- 树型 DP 入门课堂笔记
- CentOS下调用Matlab混合编程入门小节
- maven零基础入门小节和简易理解
- DP入门
- DP入门
- DP入门
- dp入门
- DP入门
- DP入门
- CPU大小端字节序的检测
- poj 3020 Antenna Placement 二分图匹配
- 从join on和where执行顺序认识T-SQL查询处理执行顺序
- 创建私有Cocoapods库
- IOS中的block的retain循环
- 树型dp入门小节
- ios申请真机调试(Xcode 5)详细解析
- 树形DP入门总结
- 绑定远程服务的流程aidl
- JVM 进阶五
- HDU 2828 Lamp
- Quartz.NET 入门(干货多多)
- 求八皇后问题的92个解并在棋盘上显示它们
- 用Linux做路由器(以VirtualBox为例):