luogu P7016 [CERC2013]Captain Obvious and the Rabbit-Man
阿新 • • 發佈:2021-06-15
問題 B: 【TEST 3】旅行
分析
此題與書上01揹包有相似之處,觀察題目,發現狀態十分好設:第一維為節點,第二維為旅遊的城市。於是,我們可以得到方程 \(dp_{i,j}=\max\limits_{k \in i} \{ \max \{ dp_{k,j},dp_{k,j-1}+a_i \} \}\),可以打出程式碼
程式碼
#include <bits/stdc++.h> #define int long long // 注意,開long long using namespace std; struct FastIO { template <typename T> FastIO& operator >> (T& in) { in = 0; char ch = getchar (); int flag = 1; for (; ! isdigit (ch); ch = getchar ()) if (ch == '-') flag = -1; for (; isdigit (ch); ch = getchar ()) in = (in << 3) + (in << 1) + (ch ^ 48); in *= flag; return *this; } }fin; const int MaxN = 1e4 + 100, MaxK = 1e3 + 100; int n, k; int a[MaxN]; int nxt[MaxN << 1], to[MaxN << 1], head[MaxN], cnt; int dp[MaxN][MaxK]; void add (int u, int v) { ++ cnt; to[cnt] = v; nxt[cnt] = head[u]; head[u] = cnt; return ; } void dfs (int d, int pre) { // 樹形dp遞迴板子 bool flag = 1; for (int i = head[d]; i; i = nxt[i]) { if (pre != to[i]) { flag = 0; dfs (to[i], d); for (int j = 0; j <= k; ++ j) { if (j == 0) { dp[d][j] = 0; } else { dp[d][j] = max (dp[d][j], max (dp[to[i]][j - 1] + a[d], dp[to[i]][j])); } } } } if (flag) { dp[d][0] = 0; dp[d][1] = a[d]; } } main () { memset (dp, 128, sizeof (dp)); fin >> n >> k; for (int i = 1; i <= n; ++ i) fin >> a[i]; for (int i = 1; i <= n - 1; ++ i) { int x, l; fin >> x >> l; add (x, l); add (l, x); } dfs (1, 0); int ans = 0; for (int i = 0; i <= k; ++ i) ans = max (ans, dp[1][i]); printf ("%lld\n", ans); return 0; } /* 5 2 2 4 1 3 2 1 2 1 3 3 4 1 5 */