zoukankan      html  css  js  c++  java
  • 【[SDOI2008]山贼集团】

    非常好的一道题

    树上的状压(dp)

    根据数据范围我们就能知道这是一道需要状压的题目

    所以状态就是(dp[i][S])表示在以(i)为根的子树里,选择的状态为(S)的最大收益

    这个收益只是在子树内部的收益,我们往上转移的时候继续加

    显然这个东西类似于一个树上背包,我们子树和根顺次合并就好了

    由于这里的体积是状态,所以我们可以直接枚举子集进行转移

    方程

    [dp[i][s]=max(dp[j][t]+dp[i][s xor t]) ]

    代码

    #include<cstring>
    #include<cstdio>
    #include<iostream>
    #define re register
    #define min(a,b) ((a)<(b)?(a):(b))
    #define max(a,b) ((a)>(b)?(a):(b))
    #define lowbit(x) ((x)&(-x))
    struct E
    {
        int v,nxt;
    }e[201];
    inline int read()
    {
        char c=getchar();
        int x=0,r=1;
        while(c<'0'||c>'9') {if(c=='-') r=-1;c=getchar();}
        while(c>='0'&&c<='9')
            x=(x<<3)+(x<<1)+c-48,c=getchar();
        return x*r;
    }
    int deep[101],head[101];
    int map[101][13];
    int num,M,n,m,ans=-999999999;
    inline void add_edge(int x,int y)
    {
        e[++num].v=y;
        e[num].nxt=head[x];
        head[x]=num;
    }
    int dp[101][4099],val[4099];
    inline int tot(int x)
    {
        int num=0;
        while(x) num++,x>>=1;
        return num;
    }
    void pre(int x,int fa)
    {
        deep[x]=deep[fa]+1;
        for(re int i=head[x];i;i=e[i].nxt)
        if(!deep[e[i].v]) pre(e[i].v,x);
    }
    void dfs(int x)
    {
        for(re int i=head[x];i;i=e[i].nxt)
        if(deep[e[i].v]>deep[x])
        {
            dfs(e[i].v);
            for(re int s=M;s;s--)
                for(re int t=s;t;t=t=(t-1)&s)
                    dp[x][s]=max(dp[x][s],dp[x][s^t]+dp[e[i].v][t]);
        }
        for(re int s=0;s<=M;s++)
        	dp[x][s]+=val[s];
    }
    int main()
    {
        n=read(),m=read();
        int x,y;
        for(re int i=1;i<n;i++)
            x=read(),y=read(),add_edge(x,y),add_edge(y,x);
        M=(1<<m)-1;
        for(re int i=1;i<=n;i++)
        {
            for(re int j=1;j<=m;j++)
                map[i][j]=read();
            for(re int j=1;j<=M;j++)
                dp[i][j]=dp[i][j^lowbit(j)]-map[i][tot(lowbit(j))];
        }
        int T=read();
        int V,C;
        while(T--)
        {
            int s=0,x=0;
            V=read(),C=read();
            for(re int i=1;i<=C;i++)
                x=read(),s|=(1<<(x-1));
            int p=s^M;
            for(re int t=p;t;t=(t-1)&p)
                val[(t|s)]+=V;
            val[s]+=V;
        }
        pre(1,0);
        dfs(1);
        std::cout<<dp[1][M];
        return 0;
    }
    
  • 相关阅读:
    OpenSSL生成证书、密钥
    js中对String去空格
    正则表达式
    webapi调用
    记一次完整的CI持续集成配置过程(.net core+Jenkins+Gitea)
    处理asp.net core连接mysql的一个异常Sequence contains more than one matching element
    asp.net core 3.1+mysql8.0+Hangfire遇到的异常解决记
    升级到asp.net core 3.1遇到的json异常
    了解ASP.NET Core端点路由
    asp.net core 2.2升到3.1遇到的问题小记
  • 原文地址:https://www.cnblogs.com/asuldb/p/10206148.html
Copyright © 2011-2022 走看看