zoukankan      html  css  js  c++  java
  • P2465 [SDOI2008]山贼集团 dp

    这个题是一道树形dp+状压dp二合一,先预处理每种组合会有什么额外的费用,然后在树上dp就行了。

    题干:

    题目描述
    
    某山贼集团在绿荫村拥有强大的势力,整个绿荫村由N个连通的小村落组成,并且保证对于每两个小村落有且仅有一条简单路径相连。小村落用阿拉伯数字编号为1,2,3,4,…,n,山贼集团的总部设在编号为1的小村落中。山贼集团除了老大坐镇总部以外,其他的P个部门希望在村落的其他地方建立分部。P个分部可以在同一个小村落中建设,也可以分别建设在不同的小村落中。每个分部到总部的路径称为这个部门的管辖范围,于是这P个分部的管辖范围可能重叠,或者完全相同。在不同的村落建设不同的分部需要花费不同的费用。每个部门可能对他的管辖范围内的小村落收取保护费,但是不同的分部如果对同一小村落同时收取保护费,他们之间可能发生矛盾,从而损失一部分的利益,他们也可能相互合作,从而获取更多的利益。现在请你编写一个程序,确定P个分部的位置,使得山贼集团能够获得最大的收益。
    输入输出格式
    输入格式:
    
    输入文件第一行包含一个整数N和P,表示绿荫村小村落的数量以及山贼集团的部门数量。
    
    接下来N-1行每行包含两个整数X和Y,表示编号为X的村落与编号为Y的村落之间有一条道路相连。(1<=X,Y<=N)
    
    接下来N行,每行P个正整数,第i行第j个数表示在第i个村落建设第j个部门的分部的花费Aij。
    
    然后有一个正整数T,表示下面有T行关于山贼集团的分部门相互影响的代价。(0<=T<=2p)
    
    最后有T行,每行最开始有一个数V,如果V为正,表示会获得额外的收益,如果V为负,则表示会损失一定的收益。然后有一个正整数C,表示本描述涉及的分部的数量,接下来有C个数,Xi,为分部门的编号(Xi不能相同)。表示如果C个分部Xi同时管辖某个小村落(可能同时存在其他分部也管辖这个小村落),可能获得的额外收益或者损失的收益为的|V|。T行中可能存在一些相同的Xi集合,表示同时存在几种收益或者损失。
    
    输出格式:
    
    输出文件要求第一行包含一个数Ans,表示山贼集团设置所有分部后能够获得的最大收益。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define duke(i,a,n) for(register int i = a;i <= n;++i)
    #define lv(i,a,n) for(register int i = a;i >= n;--i)
    #define clean(a) memset(a,0,sizeof(a))
    const int INF = 1 << 30;
    typedef long long ll;
    typedef double db;
    template <class T>
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x)
    {
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    const int N = 110;
    int lst[N],len = 0;
    int dp[N][4200];
    int val[4200];
    struct node
    {
        int l,r,nxt;
    }a[N << 1];
    int n,m;
    void add(int x,int y)
    {
        a[++len].l = x;
        a[len].r = y;
        a[len].nxt = lst[x];
        lst[x] = len;
    }
    void initdp()
    {
        int cost[N][13];
        duke(i,1,n)
        {
            duke(j,0,m - 1)
            {
                read(cost[i][j]);
            }
            dp[i][0] = 0;
            for(int j = 1;j < (1 << m);++j)
            {
                int lowbit = j & (-j);
                int lowid = (log(lowbit) + 0.001) / log(2);
                dp[i][j] = dp[i][j ^ lowbit] - cost[i][lowid];
            }
        }
    }
    void calval(int x)
    {
        duke(i,1,x)
        {
            int v,cnt,s = 0;
            read(v);read(cnt);
            duke(j,1,cnt)
            {
                int mem;
                read(mem);
                s |= (1 << (mem - 1));
            }
            int maxm = (1 << m) - 1;
            val[s] += v;
            int tmp = s ^ maxm;
            for(int j = tmp;j;j = (j - 1) & tmp)
            {
                val[(s | j)] += v;
            }
        }
    }
    void dfs(int now,int fa)
    {
        for(int k = lst[now];k;k = a[k].nxt)
        {
            int y = a[k].r;
            if(y != fa)
            {
                dfs(y,now);
                for(int j = (1 << m) - 1;j;j--)
                {
                    for(int i = j;i;i = (i - 1) & j)
                    {
                        dp[now][j] = max(dp[now][j],dp[now][j ^ i] + dp[y][i]);
                    }
                }
            }
        }
        for(int i = (1 << m) - 1;i;i--)
        {
            dp[now][i] += val[i];
        }
    }
    int main()
    {
        read(n);read(m);
        duke(i,1,n - 1)
        {
            int x,y;
            read(x);read(y);
            add(x,y);
            add(y,x);
        }
        initdp();
        int t;
        read(t);
    //    cout<<t<<endl;
        calval(t);
        dfs(1,0);
        printf("%d
    ",dp[1][(1 << m) - 1]);
        return 0;
    }
  • 相关阅读:
    STM32 F4 DAC DMA Waveform Generator
    STM32 F4 General-purpose Timers for Periodic Interrupts
    Python第十四天 序列化 pickle模块 cPickle模块 JSON模块 API的两种格式
    Python第十三天 django 1.6 导入模板 定义数据模型 访问数据库 GET和POST方法 SimpleCMDB项目 urllib模块 urllib2模块 httplib模块 django和web服务器整合 wsgi模块 gunicorn模块
    查看SQL Server服务运行帐户和SQL Server的所有注册表项
    Pycharm使用技巧(转载)
    SQL Server 2014内存优化表的使用场景
    Python第十天 print >> f,和fd.write()的区别 stdout的buffer 标准输入 标准输出 从控制台重定向到文件 标准错误 重定向 输出流和输入流 捕获sys.exit()调用 optparse argparse
    Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数
    Python第六天 类型转换
  • 原文地址:https://www.cnblogs.com/DukeLv/p/10434434.html
Copyright © 2011-2022 走看看