题意
有一颗树,上面有n个结点,每个结点的重儿子到父节点的花费为0,其他花费为1,问这棵树怎么连使得所有的花费之和最大。解析
如果我们要求深度为4的树,我们可以枚举心腹子树的长度,从1开始枚举到3,然后取其中最大的花费由此来说
不难想到通过递推来解决这个问题
并且
设为当
是花费的最大值,现在考虑递推这个结果
设表示,
个点的森林,森林中每棵树大小均不大于
,森林中所有点的深度和
若我们已经有了和所有
,则这就是一个每种物品数量不限的背包,转移可得
递推时,枚举心腹子树大小
,由于其他儿子的子树大小都不能大于
,因此递推公式
代码
#include <cctype>
#include <cfloat>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <istream>
#include <iterator>
#include <list>
#include <map>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#define ll long long
using namespace std;
const int maxn=8005;
const int MOD=998244353;
int i,j,n,dp[maxn][maxn],f[maxn];
int main(void)
{
f[1]=0;
cin>>n;
for(i=1;i<=n;i++)
dp[1][i]=i;
for(i=2;i<=n;i++){
for(j=1;j<i;j++)f[i]=max(f[i],f[j]+dp[j][i-1-j]);
for(j=0;j<=n;j++)dp[i][j]=dp[i-1][j];
for(j=i;j<=n;j++)dp[i][j]=max(dp[i][j],dp[i][j-i]+f[i]+i);
}
cout<<f[n]<<endl;
return 0;
} 
京公网安备 11010502036488号