zoukankan      html  css  js  c++  java
  • 【简】题解 P4297 [NOI2006]网络收费

    传送门:P4297 [NOI2006]网络收费 

    题目大意:

    给定一棵满二叉树,每个叶节点有一个状态(0,1),任选两个叶节点,如果这两个叶节点状态相同但他们的LCA所管辖的子树中的与他们状态相同的叶节点个数较少(少于1/2),则会产生2f的代价,如果状态不同,则产生f的代价,如果状态相同且LCA管辖子树中与他们状态相同叶节点个数较多,则不产生代价,现在每个节点可以变更状态,但变更状态也有自己的代价,求最小总代价(来自leozhang大佬)

    QWQ:

    因为各个点互相之间的贡献由各个点之间的LCA的状态

    所以考虑从根节点枚举当前点是A多还是B多的状态

    因为直接再枚举其子节点的AB个数dfs显然不合理

    考虑从子节点往上枚举AB个数做背包

    显然各节点贡献可以分开计算

    因为显然不可能在统计该节点时记录叶子节点的所有状态

    所以提前计算所有叶子节点费用

    记录每个叶子节点在他各种祖先的不同状态的贡献

    计算叶子节点贡献时算一遍就好了

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define C getchar()-48
    inline ll read()
    {
        ll s=0,r=1;
        char c=C;
        for(;c<0||c>9;c=C) if(c==-3) r=-1;
        for(;c>=0&&c<=9;c=C) s=(s<<3)+(s<<1)+c;
        return s*r;
    } 
    const ll N=2060,inf=1ll<<60;
    ll n,gs,ans=inf;
    ll f[N][2],a[N],dp[N][N],c[N][12],pd[20];
    inline int lca(int a,int b)
    {
        for(int i=n-1;i>=0;i--) if((a>>i)!=(b>>i)) return n-i-1;
    }
    inline void dfs(int x,int cs)
    {
        for(int i=0;i<=1<<n;i++) dp[x][i]=inf;
        if(cs==n)
        {
            dp[x][0]=f[x-gs][0];
            dp[x][1]=f[x-gs][1];
            for(int i=0;i<n;i++) dp[x][pd[i]^1]+=c[x-gs][i];
            return;
        }
        pd[cs]=1;dfs(x<<1,cs+1),dfs(x<<1|1,cs+1);
        for(int i=0;i<=1<<(n-cs-1);i++)   
        for(int j=(1<<(n-cs-1))+1-i;j<=1<<(n-cs-1);j++)  
          dp[x][i+j]=min(dp[x][i+j],dp[x<<1][i]+dp[x<<1|1][j]);
          
        pd[cs]=0;dfs(x<<1,cs+1),dfs(x<<1|1,cs+1);
        for(int i=0;i<=1<<(n-cs-1);i++)   
        for(int j=0;i+j<=1<<(n-cs-1);j++) 
          dp[x][i+j]=min(dp[x][i+j],dp[x<<1][i]+dp[x<<1|1][j]);
    }
    int main()
    {
        n=read();gs=(1<<n);
        for(int i=0;i<gs;i++) a[i]=read();
        for(int i=0;i<gs;i++) f[i][a[i]]=0,f[i][a[i]^1]=read();
        for(int i=0;i<gs;i++)  
        for(int j=i+1;j<gs;j++)
        {
            int rt=lca(i,j),v=read();
            c[i][rt]+=v,c[j][rt]+=v;
        }
        dfs(1,0);
        for(int i=0;i<=gs;i++) ans=min(ans,dp[1][i]); 
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    后台管理、编辑器上传图片、修改用户头像、bbs小总结
    侧边栏制作成inclusion_tag、文章的点赞点踩、文章的评论
    登陆功能、bbs首页搭建、admin后台管理、首页文章展示、用户头像展示、图片防盗链、个人站点页面搭建、侧边栏展示功能、侧边栏筛选功能、将侧边栏制作成inclusion_tag
    表创建及同步、注册功能、登陆功能、搭建bbs首页
    毕设进度7
    毕设进度6
    毕设进度5
    毕设进度4
    毕设进度3
    学习进度2
  • 原文地址:https://www.cnblogs.com/1436177712qqcom/p/11135189.html
Copyright © 2011-2022 走看看