牛客国庆集训派对Day6(kingdom)

链接:https://www.nowcoder.com/acm/contest/206/F
思路:我们考虑对于一个n,因为国王是最高上司,所以国王就是树的根,那么整个的和的最大值就等于各个子树的和的最大值+总结点数-结点树最多的子树的结点个数-1,因为各个子树可以重复出现,让我们想起了多重背包,我们考虑用f[i]表示当前i个结点总和的最大值,用g[i][j]表示总和为j,其最大子树的总结点数不超过i时的最大值,那么我们就很容易得到状态转移方程:
f[i] = max(f[i],f[j] + g[j][i-j-1]+i-j-1); 1<=j<i
同时我们要维护整个g[i][j],当j<i时有
g[i][j] = g[i-1][j];
当j>=i时有
g[i][j] = max(g[i][j],g[i][j-i]+f[i]);
做一遍复杂度为(n^2)的dp即可
代码:

#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn = 8005;
int f[maxn];//f[i]:第i个点时的答案
int g[maxn][maxn];//g[i][j],总和为j,最大子树和不超过i时的答案
int n;

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        for(int j=1;j<i;j++)f[i] = max(f[i],f[j] + g[j][i-j-1]+i-j-1);
        for(int j=1;j<=n;j++){
            g[i][j] = g[i-1][j];
            if(j>=i)g[i][j] = max(g[i][j],g[i][j-i]+f[i]);
        }        
    }
    printf("%d\n",f[n]);
    return 0;
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 原文地址:http://theory.stanford.edu/~amitp/GameProgramming/ 1...
    达微阅读 19,792评论 0 28
  • 小心,大意。 怎么才能把时间掌握到刚刚好呢,本来早就可以准备今晚的MS内容,然而一拖再拖,就这样了。 下不为例。 ...
    林凡_阅读 942评论 1 0
  • 光说不练假把式,光练不说假坚持。
    飞的更好阅读 1,495评论 0 0
  • 大多时候我们只是察觉而没有去思索,比如察觉生命,察觉成长,察觉时间,察觉皱纹,察觉疼痛,察觉死亡,察觉希望,或者绝...
    莲花馆主阅读 2,047评论 0 0
  • 家豪: 你好。 今天你在作业本里跟我说,你恨我不相信你。就这个话题,我想跟你说说我一直都想跟你说清...
    _荷包蛋_阅读 3,777评论 0 0