UVALive 7003 A Balance Game on Trees 树形dp
来源:互联网 发布:网络存储的用处 编辑:程序博客网 时间:2024/05/30 02:53
题意:
有一颗<=100的树,树上的节点一开始全部都是白色。
现在要求,每个白色节点必须刚好和k个黑点相邻,不能则将其染黑,问你最终最多可以有多少个白色节点保留。
思路:
树形dp
特判掉k = 0的情况;
dp[i][j][z]:以i为根节点的子树,节点i的颜色为j,和它相连有z个黑色节点所得到的最多的白色节点个数。
由于z只有k-1和k两种状态是有用的。因此我们只需要处理出三种状态。
dp[i][0][0]:i节点白色,子树有k-1个黑色节点与i相邻
dp[i][0][1]:i节点白色,子树有k歌黑色节点与i相邻
dp[i][1][0]:i节点黑色,有多少个黑色节点都无所谓
当前节点i,对于i的直接儿子节点,我们只要再进行一次dp将它们合并即可。
dp2[t][p]:前t个儿子节点,有p个黑色节点与i相邻,所得到的最大白色节点个数。
具体转移看代码(写得比较挫= =)
code:
#include <bits/stdc++.h>using namespace std;const int N = 105;typedef long long LL;int n, k;char ch[10000];int dp[N][2][2];int dp2[2][N];int head[N], ec = 0;struct PP { int v, next;}edge[N<<1];void addEdge(int u, int v) { edge[ec] = (PP){v, head[u]}; head[u] = ec++;}void dfs(int u, int par) { bool flag = false; vector <int> a, b, c; for(int i = head[u];i != -1; i = edge[i].next) { int v = edge[i].v; if(v == par) continue; dfs(v, u); flag = true; a.push_back(dp[v][0][1]); //k b.push_back(dp[v][1][0]); c.push_back(dp[v][0][0]); //k-1 } //leaf node if(!flag) { if(k == 1) { dp[u][0][0] = 1; dp[u][0][1] = -1; dp[u][1][0] = 0; } else { dp[u][0][0] = dp[u][0][1] = -1; dp[u][1][0] = 0; } return ; } //deal memset(dp2, -1, sizeof(dp2)); dp2[0][0] = 0; int cur = 0; int n = a.size(); for(int i = 0;i < n; i++) { for(int j = 0;j <= n; j++) { if(dp2[cur][j] == -1) continue; if(a[i] != -1) { dp2[cur^1][j] = max(dp2[cur^1][j], dp2[cur][j]+a[i]); } if(b[i] != -1) { dp2[cur^1][j+1] = max(dp2[cur^1][j+1], dp2[cur][j]+b[i]); } dp2[cur][j] = -1; } //memset(dp2[cur], -1, sizeof(dp2[cur])); cur ^= 1; } //dp[u][0][0], dp[u][0][1]; if(dp2[cur][k-1] != -1) dp[u][0][0] = dp2[cur][k-1]+1; if(dp2[cur][k] != -1) dp[u][0][1] = dp2[cur][k]+1; //dp[u][1][0] dp[u][1][0] = 0; for(int i = 0;i < n; i++) { dp[u][1][0] += max(b[i], c[i]); }}void solve() { if(k == 0) { printf("%d\n", n); return ; } memset(dp, -1, sizeof(dp)); dfs(1, -1); printf("%d\n", max(dp[1][0][1], dp[1][1][0]));} int main() { int T; scanf("%d", &T); while(T--) { memset(head, -1, sizeof(head)), ec = 0; scanf("%d%d", &n, &k); int tmp; getchar(); for(int i = 1;i <= n; i++) { gets(ch); stringstream str(ch); while(str>>ch) { sscanf(ch, "%d", &tmp); if(tmp == 0) break; addEdge(i, tmp); addEdge(tmp, i); } } solve(); } return 0;}
0 0
- UVALive 7003 A Balance Game on Trees 树形dp
- UVALive 7003 A Balance Game on Trees(树形dp)
- Perfect Domination on Trees [UVALive 3346] 树形DP
- UVALIVE 3346 Perfect Domination on Trees 树形DP
- UVALive 6919 A game for kids(树形dp)
- 【树形dp】UVALive 2038 Strategic game
- UVALive 2038 Strategic game--树形dp
- UVALive 2038 Strategic game (树形DP,4级)
- UVALive 2038 - Strategic game (经典树形DP)
- UVALive 4015 树形dp
- 树形DP--HihoCoder1063 Travel On a Tree
- UVALive 3683 A Scheduling Problem(树形DP)
- CodeForce 280C Game on Tree -- 树形dp求期望
- Codeforces 280C Game on Tree 树形期望dp
- 简单树形dp uvaLive 4472
- UVALive - 4015 Caves 树形DP
- UVALive 4015 - Caves(树形DP)
- uvalive 4015 树形背包dp
- jdk7安装及配置
- 【codevs2833】奇怪的梦境 拓扑排序
- Reverse Linked List(C++)
- OC属性
- ACM-ICPC国际大学生程序设计竞赛长春赛区(2015)地区赛有感
- UVALive 7003 A Balance Game on Trees 树形dp
- Fedora 12无法联网情况下安装gcc
- UI - RequestNetWork
- bzoj1642[Usaco2007 Nov]Milking Time 挤奶时间
- 用两个栈实现队列
- 在有序但是含有空的字符串中查找最左边特定字符串的位置
- 【四】GlusterFS管理员手册
- 秒针国家统计局项目:我的一些感想和8点安全措施
- 数据库连接池DBPool分析(八):redis连接池 redis_connection_pool