NC19810(dp)

https://ac.nowcoder.com/acm/problem/19810
这题有个结论比较好猜……
题目大意是,给定n要求构造一棵权值最大的树,如果一个点是父亲的重儿子,那么权值等于父亲,否则等于父亲权值+1,根权值=0。
设i个节点的树的最大权值是dp[i],然后当我们想构造一棵大小为n的树时,根节点是0,接下来n-1个点形成一个森林,设其中最大树大小为k,那么dp[n]的值就由这些子树的dp值构成,其中,对于除了重子树的节点,都有额外的权值1,所以dp[n]=dp[k]+sum(dp[ai])+n-1-k,其中sum(ai)=n-k-1,max(ai)<=k。
所以核心算法就是,对于固定的n遍历其最大树k,然后对于每个k,找到合法森林的最大权值再加上n-k,这里的难题在于我们不知道对于剩下n-k个顶点如何构建出最大权值的森林。这时可以大胆做出一个猜测:将剩下n-k个点尽可能凑成k大的树,剩余不足的单独一棵树。因为最终结果一定是这种结构的,如果不是的话说明有别的树“性价比”更高,那就尽可能采用那棵树好了。
当然这个猜想也没证明正确,嘤嘤嘤,希望证实/伪的大佬可以分享一下

#include<bits/stdc++.h>
using namespace std;

const int maxn=8004;

int dp[maxn];

int main(){
    int n;
    cin>>n;
    for(int i=3;i<=n;i++){
        for(int j=1;j<i;j++){
            dp[i]=max(dp[i],(i-1)/j*dp[j]+dp[(i-1)%j]+i-1-j);
        }
    }
    cout<<dp[n]<<endl;
}
每日一题 文章被收录于专栏

暑期每日一题,尽量日更

全部评论

相关推荐

11-04 14:10
东南大学 Java
_可乐多加冰_:去市公司包卖卡的
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务