题目描述

某山贼集团在绿荫村拥有强大的势力,整个绿荫村由\(N\)个连通的小村落组成,并且保证对于每两个小村落有且仅有一条简单路径相连。

小村落用阿拉伯数字编号为\(1,2,3,4, \dots ,n\),山贼集团的总部设在编号为\(1\)的小村落中。

山贼集团除了老大坐镇总部以外,其他的\(P\)个部门希望在村落的其他地方建立分部。

\(P\)个分部可以在同一个小村落中建设,也可以分别建设在不同的小村落中。每个分部到总部的路径称为这个部门的管辖范围,于是这\(P\)个分部的管辖范围可能重叠,或者完全相同。

在不同的村落建设不同的分部需要花费不同的费用。每个部门可能对他的管辖范围内的小村落收取保护费,但是不同的分部如果对同一小村落同时收取保护费,他们之间可能发生矛盾,从而损失一部分的利益,他们也可能相互合作,从而获取更多的利益。

现在请你编写一个程序,确定\(P\)个分部的位置,使得山贼集团能够获得最大的收益。

输入格式

输入文件第一行包含一个整数\(N\)和\(P\),表示绿荫村小村落的数量以及山贼集团的部门数量。

接下来\(N-1\)行每行包含两个整数\(X\)和\(Y\),表示编号为\(X\)的村落与编号为\(Y\)的村落之间有一条道路相连。(\(1 \le X,Y \le N\))

接下来\(N\)行,每行\(P\)个正整数,第\(i\)行第\(j\)个数表示在第\(i\)个村落建设第\(j\)个部门的分部的花费\(A_{i,j}\)。

然后有一个正整数\(T\),表示下面有\(T\)行关于山贼集团的分部门相互影响的代价。(\(0 \le T \le 2 \times p\))

最后有\(T\)行,每行最开始有一个数\(V\),如果\(V\)为正,表示会获得额外的收益,如果\(V\)为负,则表示会损失一定的收益。

然后有一个正整数\(C\),表示本描述涉及的分部的数量,接下来有\(C\)个数,\(X_i\),为分部门的编号(\(X_i\)不能相同)。

表示如果\(C\)个分部\(X_i\)同时管辖某个小村落(可能同时存在其他分部也管辖这个小村落),可能获得的额外收益或者损失的收益为的\(|V|\)。

\(T\)行中可能存在一些相同的\(X_i\)集合,表示同时存在几种收益或者损失。

输出格式

输出文件要求第一行包含一个数\(Ans\),表示山贼集团设置所有分部后能够获得的最大收益。

输入输出样例

输入 #1
2 1
1 2
2
1
1
3 1 1
输出 #1
5

说明/提示

对于\(40%\)的数据,\(1 \le P \le 6\)。

对于\(100%\)的数据,\(1 \le N \le 100\),\(1 \le P \le 12\),保证答案的绝对值不超过\({10}^8\)。

解题报告

算法解析

剖析题意

首先我们分析题意,这道题目其实给了很多关键性的信息,我们可以提取

  1. 树上结构

  2. 每一个部门有着二进制状态,可以选择,或者不可以选择

  3. 数据范围特别小

综上所述,我们不难发现,这道题目与,树型DP,状压DP有着很大的联系.


状压设置

不难设置出,我们应该以\(p\)进行状压.

  1. 唯独他,范围小
  2. 分部门的总数

总而言之,状态设计为如下.

\[S:每一个分部门是否选择
\]

.假如说

\[S=1101
\]

那么表示为,选择,\(1,3,4\)这三个分部门


价值定义

我们发现,题目给出的一个关键地方为,不同分部门之间存在影响

既然如此,我们不妨思考一下,对于每一个状态,他们肯定有一个权值.

而这个权值,必然就是若干个分部门同时选择,产生的价值.

举个栗子

\[1,3分部门选择,价值为5
\]

然后.

\[1,4分部门选择,价值为-3
\]

现在我们选择的状态为.

\[S=1101
\]

那么请问这个状态,它是什么价值呢?

\[val[S]=5-3=2
\]

因此对于这类状态,我们显然是要存储下来他们的价值的.

\[val[S]表示S状态的价值
\]


树型阶段

现在我们这个状态是出现了,但是阶段还没有划分好.

其实树型DP的阶段是最好划分的.

因为它的阶段就是以,父子节点作为分段.

既然如此,我们设计一下.

\[f[i][S]表示在以i为根的子树里,分部门选择状态为S的最大收益
\]

那么这样,我们的状态表示就设置完毕了.


状态转移

状态已经设置完毕,我们现在缺失的就是动态规划的状态转移.

我们先来思考一些问题.

  1. 对于一个集合,它会被那些集合转移过来呢?

换句话说,就是有哪些符合条件的\(S'\)满足下面这个条件

\[S' => S
\]

我们发现.

\[S' \in S
\]

也就是说,\(S'\)是\(S\)的子集

  1. 从一个集合转移到另外一个集合,代价为什么

我们需要回顾一下定义.

\[val[S]表示S状态的价值
\]

那么既然如此,一个集合状态它的代价,不就是.

\[val[S]
\]

这就是转移的代价,从一个状态到另外一个状态

  1. 树上怎么转移

①从儿子节点到父亲节点.

②从子集当前集合

所以说我们的表达为

\[f[x][S]=f[x][s']+f[son[x]][S \oplus S']
\]

但是对于这个状态表示而言,我们的类型是最大价值,而且一个点有很多个儿子节点

一个节点只能从一个儿子节点转移过来,那么这个儿子必须是价值最高的.

所以变成了.

\[f[x][S]=max(f[x][s],f[x][s']+f[son[x]][S \oplus S'])
\]

之前当前节点的状态集合为\(S'\),现在通过儿子上来的转移,现在变成了\(S\)

那么

\[f[x][S]+=val[s]
\]

然后我们分析上面这些语句.

不难发现,这个和背包问题特别相像

因此,这个转移就是树上背包转移

于是这道题目就是非常有趣的,动态规划算法大杂烩

\[背包DP+状压DP+树型DP=状态转移+状态设计+阶段转移
\]


代码解析

//本题目的算法为,背包DP+树型DP+状压DP,是一道DP的优秀题目
#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) ((x)&(-x))//x的最靠右边的1
const int N=110,S=(1<<12)+3;
int n,p,M,t,a[N][N],f[N][S],val[S];
vector<int> g[N];
inline int tot(int x)//统计x二进制表示下的位数
{
int cnt=0;
while(x)
{
cnt++;
x>>=1;
}
return cnt;
}
void dfs(int x,int fa)
{
for(int y:g[x])
{
if (y==fa)//防止遍历回到曾经访问过的节点
continue;
dfs(y,x);//访问儿子节点,自下往上的转移,这是树型DP的精华
for(int s=M; s; s--)//遍历所有集合,类似于背包问题的j,从M~1.
for(int t=s; t; t=t=(t-1)&s)//从子集转移过来
f[x][s]=max(f[x][s],f[x][s^t]+f[y][t]);//相当于加入第y个物品,它的体积是t
//也可以认为是 t->s的一种转移
}
for(int s=0; s<=M; s++)//遍历所有集合
f[x][s]+=val[s];//加上这个状态,分部门该有的影响
}
inline void init()
{
scanf("%d%d",&n,&p);
M=(1<<p)-1;//所有分部门都安排好该有的状态表示
for(int i=1; i<n; i++)
{
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v),g[v].push_back(u);//这里是添加边,以无向图的方式存储
}
for(int i=1; i<=n; i++)
{
for(int j=1; j<=p; j++)
scanf("%d",&a[i][j]);
for(int j=1; j<=M; j++)
f[i][j]=f[i][j ^ lowbit(j)]-a[i][tot(lowbit(j))];
//在这里lowbit(j)为j的第一个是1的位置.tot(lowbit(j))这个1所在的位置
}
scanf("%d",&t);
while(t--)
{
int v,c,x=0,s=0;
scanf("%d%d",&v,&c);
for(int i=1; i<=c; i++)
scanf("%d",&x),s|=(1<<(x-1));//s表示本次操作收到影响分部门集合
int p=s^M;//取出所有不受影响的位置
for(int t=p; t; t=(t-1)&p)
val[(t|s)]+=v;//所有包含s的集合,都要+v的影响
val[s]+=v;//完全包含也要+v
}
dfs(1,0);
printf("%d\n",f[1][M]);//1是根节点,M为所有分部门都安排好了,这就是最后的答案
}
signed main()
{
init();
return 0;
}

[SDOI2008]山贼集团的更多相关文章

  1. P2465 [SDOI2008]山贼集团 dp

    这个题是一道树形dp+状压dp二合一,先预处理每种组合会有什么额外的费用,然后在树上dp就行了. 题干: 题目描述 某山贼集团在绿荫村拥有强大的势力,整个绿荫村由N个连通的小村落组成,并且保证对于每两 ...

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

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

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

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

  4. 【[SDOI2008]山贼集团】

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

  5. 山贼集团 (group)

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

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

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

  7. 状压DP入门详解+题目推荐

    在动态规划的题型中,一般叫什么DP就是怎么DP,状压DP也不例外 所谓状态压缩,一般是通过用01串表示状态,充分利用二进制数的特性,简化计算难度.举个例子,在棋盘上摆放棋子的题目中,我们可以用1表示当 ...

  8. C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 - 总部业务部门主管管理整个集团分公司的某项业务

    由于整个集团公司非常庞大,有上千个分支机构,不可能由总部某个人能管理所有的数据,或者掌握所有的业务.某个业务都会由于某个相应的部门进行管理,例如所有分公司的人力资源,都由总部的人力资源部门管理.哪些分 ...

  9. BZOJ 4698: Sdoi2008 Sandy的卡片

    4698: Sdoi2008 Sandy的卡片 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 106  Solved: 40[Submit][Stat ...

随机推荐

  1. SpringBean的工作原理

    在 Spring 中,那些组成应用程序的主体及由 Spring IOC 容器所管理的对象,被称之为 bean.简单地讲,bean 就是由 IOC 容器初始化.装配及管理的对象,除此之外,bean 就与 ...

  2. CF1183E/H Subsequences

    思路: dp好题,dp[i][j]表示到前i个字符为止并且以s[i]为结尾,共有多少个长度为j的不同的子序列. 实现: #include <bits/stdc++.h> using nam ...

  3. SpringBoot整合Redis及Redis工具类

    前言 想做一个秒杀项目,问了几个大佬要了项目视频,结果,自己本地实践的时候,发现不太一样,所以写下这篇,为以后做准备. 环境配置 IDE:IDEA 环境:Windows 数据库:Redis Maven ...

  4. 2017 ICPC西安区域赛 A - XOR (线段树并线性基)

    链接:https://nanti.jisuanke.com/t/A1607 题面:   Consider an array AA with n elements . Each of its eleme ...

  5. 什么是文件存储NAS

    阿里云文件存储(Network Attached Storage,简称 NAS)是面向阿里云 ECS 实例.E-HPC 和容器服务等计算节点的文件存储服务. 定义 阿里云文件存储 NAS 是一个可共享 ...

  6. mysql 连接远程连接服务器 1130错误

    今天在用sqlyog连接非本地的Mysql服务器的数据库,居然无法连接很奇怪,报1130错误, ERROR 1130: Host 192.168.3.100 is not allowed to con ...

  7. Ural 1201 Which Day Is It? 题解

    目录 Ural 1201 Which Day Is It? 题解 题意 输入 输出 题解 程序 Ural 1201 Which Day Is It? 题解 题意 打印一个月历. 输入 输入日\((1\ ...

  8. PHP搭建B2C分销商城系统需要考虑哪些因素?(一)

    在网购日渐繁盛的今天,传统线下门店和代理分销越发显示出其弊端.此种情况下,进入互联网市场是最好的选择.入驻第三方平台成本太高,无法掌握自己的流量,所以搭建自己的分销平台成为众多企业的首选.搭建B2C分 ...

  9. 怎样初始化XMLHttpRequest实例对象xhr

    xhr.open() 接收5个参数, 用于初始化一个http请求, 它接收5个参数: 1. method: 请求类型; 2. url: 请求的url; 3. async: 是否为异步, 默认为true ...

  10. vuex项目history模式下404问题的解决方案

    在 ” etc/nginx/conf.d/  “路径下修改你的当前项目的conf文件 在location中添加,下文中加粗部分的代码,实现重写路径,以避免出现404. location / { roo ...