• Luogu P3262 [JLOI2015]战争调度


    题意

    给定一棵高度为 (n) 的完全二叉树,可以将节点设置成两种状态。如果某个叶子 (x) 的状态为 (i) 同时他的某个祖先也为 (i),那么这个叶子就会对祖先产生 (f_{x,i}) 的贡献。求叶子状态为 (0) 的数量小于等于 (m) 的最大贡献。

    ( exttt{Data Range:}1leq nleq 10,mleq 2^{n-1})

    题解

    考虑先设一个 (f_{i,j}) 表示到了 (i) 点,叶子选了 (j)(0) 的,这个子树对祖先的总贡献,但是会发现这个东西好像做不了。

    于是考虑状压。设 (f_{i,j,S}) 表示到了 (i) 点,叶子选了 (j)(0),这个点的祖先的选择的状态为 (S) 时这个字数对祖先的总贡献。

    然后这个东西就做个树形背包就好了。

    实现的时候可以考虑爆搜一下,就可以压缩掉 (S) 这一维。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef int ll;
    typedef long long int li;
    const ll MAXN=2051;
    ll n,m,sz,res;
    ll u[MAXN][15],v[MAXN][15],f[MAXN][MAXN<<1];
    inline ll read()
    {
        register ll num=0,neg=1;
        register char ch=getchar();
        while(!isdigit(ch)&&ch!='-')
        {
            ch=getchar();
        }
        if(ch=='-')
        {
            neg=-1;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            num=(num<<3)+(num<<1)+(ch-'0');
            ch=getchar();
        }
        return num*neg;
    }
    #define ls node<<1
    #define rs node<<1|1
    inline void dfs(ll node,ll sz,ll st)
    {
        for(register int i=0;i<=sz;i++)
        {
            f[node][i]=0;
        }
        if(sz==1)
        {
            for(register int i=0;i<n-1;i++)
            {
                if(st&(1<<i))
                {
                    f[node][1]+=u[node][i+1];
                }
                else
                {
                    f[node][0]+=v[node][i+1];
                }
            }
            return;
        }
        for(register int i=0;i<2;i++)
        {
            dfs(ls,sz>>1,st<<1|i),dfs(rs,sz>>1,st<<1|i);
            for(register int j=0;j<=min(sz,m);j++)
            {
                for(register int k=0;k<=min(sz,m);k++)
                {
                    f[node][j+k]=max(f[node][j+k],f[ls][j]+f[rs][k]);
                }
            }
        }
    }
    int main()
    {
        n=read(),m=read(),sz=1<<n;
        for(register int i=sz>>1;i<sz;i++)
        {
            for(register int j=1;j<=n-1;j++)
            {
                u[i][j]=read();
            }
        }
        for(register int i=sz>>1;i<sz;i++)
        {
            for(register int j=1;j<=n-1;j++)
            {
                v[i][j]=read();
            }
        }
        dfs(1,sz-1,0);
        for(register int i=0;i<=m;i++)
        {
            res=max(res,f[1][i]);
        }
        printf("%d
    ",res);
    }
    
  • 相关阅读:
    [MSDN] How to Debug a Release Build
    抽象成员 虚方法
    强制类型转换符 和 as 运算符
    一份超长的MySQL学习笔记
    Java反射基础
    c3p0config.xml
    一个JDBC封装工具类
    Spring5——IOC操作Bean管理(基于xml文件)
    Android游戏开发大全
    移除项目里的所有.svn命令
  • 原文地址:https://www.cnblogs.com/Karry5307/p/13458640.html
Copyright © 2020-2023  润新知