1 条题解
-
0
建图及调试(看看有没有建对)
#include <bits/stdc++.h> using namespace std; const int MAXN = 200; int n; int val[MAXN + 5]; // 叶子结点的画的数量 int tot; // 开了多少个节点 // <子节点 v, 边权 w> vector<pair<int, int>> e[MAXN + 5]; // 返回当前建树后的根节点以及到根节点的边权 pair<int, int> dfs() { int u, w, x; u = ++tot; cin >> w >> x; cout << w << " " << x << endl; if (x != 0) val[u] = x; else { e[u].push_back(dfs()); e[u].push_back(dfs()); } return {u, w}; } void dfsShow(int u) { for (int i = 0; i < e[u].size(); i++) { int v = e[u][i].first; int w = e[u][i].second; cout << u << "->" << v << ":" << w << endl; dfsShow(v); } } int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n; tot = 1; e[1].push_back(dfs()); dfsShow(1); // 看看树建的对不对 return 0; }
参考代码
#include <bits/stdc++.h> using namespace std; const int MAXN = 200; // 节点数量 int n; // --- 建图 --- // <子节点 v, 边权 w> vector<pair<int, int>> e[MAXN + 5]; int val[MAXN + 5]; // 叶子结点的画的数量 int tot; // 开了多少个节点 // 返回当前建树后的根节点以及到根节点的边权 pair<int, int> dfs() { int u, w, x; u = ++tot; cin >> w >> x; if (x != 0) val[u] = x; else { e[u].push_back(dfs()); e[u].push_back(dfs()); } return {u, w}; } void dfsShow(int u) { for (int i = 0; i < e[u].size(); i++) { int v = e[u][i].first; int w = e[u][i].second; cout << u << "->" << v << ":" << w << endl; dfsShow(v); } } // --- treedp 两种写法都能求出答案,但显然求 g 更快--- int f[MAXN + 5][6005]; // f[u][i] 子树 u 有 i 秒时间的最多偷画数量 int g[MAXN + 5][2005]; // g[u][i] 子树 u 偷 i 幅画的最少时间 void dfsDP(int u) { for (int i = 0; i <= val[u] * 5; i++) f[u][i] = i / 5; // 叶子节点的处理 for (int i = val[u] * 5 + 1; i <= n; i++) f[u][i] = f[u][i - 1]; for (int i = 1; i <= 2000; i++) g[u][i] = n + 1; g[u][0] = 0; for (int i = 1; i <= val[u]; i++) g[u][i] = i * 5; for (int i = 0; i < e[u].size(); i++) { int v = e[u][i].first; int w = e[u][i].second; dfsDP(v); // 求 f // 在之前的子树上花费了 j 的时间 for (int j = n; j >= 0; j--) // 在子树 i 上画了 k 的时间 for (int k = 0; j + k + 2 * w <= n; k++) f[u][j + k + 2 * w] = max(f[u][j + k + 2 * w], f[u][j] + f[v][k]); // 求 g for (int j = 2000; j >= 0; j--) for (int k = 0; k + j <= 2000; k++) { g[u][j + k] = min(g[u][j + k], g[u][j] + g[v][k] + w * 2); } } /* cout << u << ":"; for (int i = 0; i <= n; i++) cout << f[u][i] << " "; cout << "\n"; */ } int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n; tot = 1; e[1].push_back(dfs()); // dfsShow(1); dfsDP(1); // f 的输出答案 cout << f[1][n - 1] << "\n"; // g 的输出答案 for (int i = 2000; i >= 0; i--) { if (g[1][i] <= n - 1) { cout << i; break; } } return 0; }
信息
- ID
- 2084
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 35
- 已通过
- 15
- 上传者