这个题是一道树形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\n",dp[1][(1 << m) - 1]);return 0;
}

转载于:https://www.cnblogs.com/DukeLv/p/10434434.html

P2465 [SDOI2008]山贼集团 dp相关推荐

  1. 洛咕 P2465 [SDOI2008]山贼集团

    裸的状压dp. 设f[i][j]表示在i字数内放j集合的分部,直接sb转移. // luogu-judger-enable-o2 #include<bits/stdc++.h> #defi ...

  2. [SDOI2008]山贼集团【树上背包+状压】

    洛谷P2465 SOL 比较经典的一类树上背包问题套一个子集状压枚举. 注意到代价的计算与所选的点的集合有关,如果我们要统计代价需要状压记录点集,而数据范围非常配合的给了P≤12P\le12P≤12, ...

  3. 【学术篇】SDOI2008 山贼集团

    今天一月一号.. 突然想安利一波我的中二的2017总结- 传送门1:codevs 传送门2:luogu 时限5s和1s的区别(你没看我传送门都给的大牛分站了) 现在不仅线筛.. 有负数的快读都打不对了 ...

  4. 【[SDOI2008]山贼集团】

    非常好的一道题 树上的状压\(dp\) 根据数据范围我们就能知道这是一道需要状压的题目 所以状态就是\(dp[i][S]\)表示在以\(i\)为根的子树里,选择的状态为\(S\)的最大收益 这个收益只 ...

  5. 【SDOI2008】山贼集团

    本题的模型是树形状态压缩的动态规划. 首先考虑简单的题目模型:对于任何形态的有根树 T,都可以建立其等效二叉树 T',若在原树 T 中,结点 x 有儿子c1,c2,c3,-,ck c1,c2,c3,- ...

  6. [FROM WOJ]#2040 山贼集团

    #2040 山贼集团 SDOI2008 题面 某山贼集团在绿荫村拥有强大的势力,整个绿荫村由N个连通的小村落组成,并且保证对于每两个小村落有且仅有一条简单路径相连.小村落用阿拉伯数字编号为1,2,3, ...

  7. 山贼集团 (group)

    山贼集团 (group) 题目描述 某山贼集团在绿荫村拥有强大的势力,整个绿荫村由N个连通的小村落组成,并且保证对于每两个小村落有且仅有一条简单路径相连.小村落用阿拉伯数字编号为1,2,3,4,-,n ...

  8. 【Luogu】P2465山贼集团(树形状压DP)

    题目链接 写了个70分暴力还挂了,第一遍提交只拿了十分--海星 首先建虚拟节点多叉树转成二叉,然后子集枚举DP 设g[x][i]是以x为根的子树内山贼集合i,x啥都不选也没贡献的时候的最大价值 f[x ...

  9. 「SDOI 2008」山贼集团

    传送门 problem 给定一棵 nnn 个点且根为 111 的树,有 ppp 个部门,每个部门会占据一个点,占据点会有代价,不同部门可以占据同一个点,每个部门的管辖范围是 111 到他占据点的链上的 ...

最新文章

  1. 滴滴开源在2019:十大重点项目盘点,DoKit客户端研发助手首破1万Star
  2. 002_SpringBoot整合Servlet
  3. 七、linux驱动注册
  4. php 频繁dom和 文件,性能优化之为什么不要频繁操作DOM
  5. [vue] vue使用v-for遍历对象时,是按什么顺序遍历的?如何保证顺序?
  6. 代码审查:程序员内炼之道
  7. 3-17Pytorch与线性代数运算
  8. ARM中R0-R15寄存器的作用
  9. fatal: unable to access ‘https://github.com/abseil/abseil-cpp.git/‘: Failed connect to github.com:44
  10. 全面了解风控数据体系
  11. 计算机excel表格公式教程,职称计算机Excel教程:显示公式的方法
  12. Cura工程环境配置教程
  13. 批量下载ERA5数据(Python+IDM)
  14. 知云文献,Endnote简易使用指南
  15. 跳槽重回前公司?当初的离职原因没解决,早晚还得辞职
  16. OpenGL显示文字--显示英文
  17. ESP8266 下载报错please check partition type 6 addr:3fd000 len:3000
  18. python三大器,Python 入门之 Python三大器 之 生成器
  19. ITON RW6852-50S WIFI6模组
  20. 3dmax第二次安装遇到的问题及解决方案

热门文章

  1. TCP/IP_UDP归纳
  2. 涂鸦智能宠物喂食器(鱼缸投食器)
  3. python读取nii文件、nii.gz文件
  4. 基于墨刀的视频剪辑软件Xshow原型化系统
  5. LuaForWindows(SciTE) 5.1 常见问题
  6. 将idea中文显示转化成英文
  7. 文件处理小程序(包含哈夫曼文件压缩-解压等 C语言)
  8. 熟悉Elipse开发工具
  9. Java用普里姆算法(prim)解决修路最短路径问题
  10. 关于计算机的优点英语作文,初三英语作文电视电脑的优缺点