P2015 二叉苹果树
题目
P2015 二叉苹果树
算法标签: 动态规划, 树上 d p dp dp, 树上背包问题, d f s dfs dfs, 记忆化搜索
思路
题目中表示的很明确, 给出了需要保留的树枝的数量, 可以理解为背包的容量, 因此可以定义状态表示 f [ i ] [ j ] f[i][j] f[i][j]表示以 i i i为根节点的子树中, 保留的树枝数量不超过 j j j的所有方案中价值最大的方案, 对于当前根节点 i i i来说子节点的选择是有 2 k 2 ^ k 2k种的, k k k是子节点的数量
代码
#include <iostream>
#include <algorithm>
#include <cstring>using namespace std;const int N = 110, M = N << 1;int n, m;
int head[N], ed[M], ne[M], w[M], idx;
int f[N][M];void add(int u, int v, int val) {ed[idx] = v, ne[idx] = head[u], w[idx] = val, head[u] = idx++;
}void dfs(int u, int fa) {for (int i = head[u]; ~i; i = ne[i]) {int v = ed[i];if (v == fa) continue;dfs(v, u);for (int j = m; j >= 0; --j) {for (int k = 0; k < j; ++k) {f[u][j] = max(f[u][j], f[u][j - k - 1] + f[v][k] + w[i]);}}}
}int main() {ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);memset(head, -1, sizeof head);cin >> n >> m;for (int i = 0; i < n - 1; ++i) {int u, v, w;cin >> u >> v >> w;add(u, v, w), add(v, u, w);}dfs(1, -1);int ans = f[1][m];cout << ans << "\n";return 0;
}