https://www.luogu.com.cn/problem/P4438
这个神仙问题告诉我们,树形dp还是dp,动态规划是真的难,不会设转移方程要吃大亏
写成记忆话搜索是真的方便,服了
#include<iostream> #include<cstring> #include<cstdio> #include<queue> #include<algorithm> #include<vector> using namespace std; typedef long long ll; const int maxn = 22000; ll INF = 1e16; int n; //-----------------建立边部分 ll dp[22000][44][44]; ll a[22000], b[22000], c[22000]; int son[22000][3]; ll dfs(int x, int i, int j) { if (x < 0) { int xx = -x; return 1LL*c[xx] * (a[xx] + i)*(b[xx] + j); } if (dp[x][i][j] < INF) return dp[x][i][j]; return dp[x][i][j] = min(dfs(son[x][0], i, j) + dfs(son[x][1], i, j + 1), dfs(son[x][0], i+1, j) + dfs(son[x][1], i, j)); } int main() { for (int i = 0; i < maxn; i++) { for (int j = 0; j < 44; j++) { for (int k = 0; k < 44; k++) { dp[i][j][k] = INF; } } } scanf("%d", &n); int be, en; for (int i = 1; i < n; i++) { scanf("%d%d", &be, &en); son[i][0] = be; son[i][1] = en; } for (int i = 1; i <= n; i++) { scanf("%lld%lld%lld", &a[i], &b[i], &c[i]); } int root = 1; ll ans = dfs(root, 0, 0); cout << ans << endl; return 0; }