题目链接:https://www.nowcoder.com/acm/contest/206/F
题意:一棵 n 个点的树,根为 1,重儿子到父亲的费用为 0,其余为 1,问所有点到 1 的最大总费用是多少。
题解:ans[i]为 i 个点时候的最大费用,dp[i][j]表示若干棵树总大小为 j 并且每棵树的大小不超过 i 时的最大费用,每次循环首先枚举重儿子的大小更新 ans[i],而ans[i]更新后会对每棵树大小最大为 i 的dp数组产生影响,枚举若干棵树的总大小dp[i][j]。
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define ull unsigned long long 5 #define mst(a,b) memset((a),(b),sizeof(a)) 6 #define mp(a,b) make_pair(a,b) 7 #define pi acos(-1) 8 #define pii pair<int,int> 9 #define pb push_back 10 const int INF = 0x3f3f3f3f; 11 const double eps = 1e-6; 12 const int MAXN = 8e3 + 10; 13 const int MAXM = 2e6 + 10; 14 15 int ans[MAXN],dp[MAXN][MAXN]; 16 17 int main() { 18 #ifdef local 19 freopen("data.txt", "r", stdin); 20 #endif 21 int n; 22 scanf("%d",&n); 23 for(int i = 1; i <= n; i++) dp[1][i] = i; 24 for(int i = 2; i <= n; i++) { 25 for(int j = 1; j < i; j++) ans[i] = max(ans[i], ans[j] + dp[j][i - 1 - j]); 26 for(int j = 0; j < i; j++) dp[i][j] = dp[i - 1][j]; 27 for(int j = i; j <= n; j++) dp[i][j] = max(dp[i - 1][j], dp[i][j - i] + ans[i] + i); 28 } 29 printf("%d ",ans[n]); 30 return 0; 31 }