牛客国庆集训派对Day6 && CCPC-WannaFly-Camp #1 F. kingdom

题目链接: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\n",ans[n]);
30     return 0;
31 }

猜你喜欢

转载自www.cnblogs.com/scaulok/p/9748238.html