<更新提示>

<第一次更新> 通过两道简单的例题,我们来重新认识树形DP。


<正文>

战略游戏(luoguP1026)

Description

Bob喜欢玩电脑游戏,特别是战略游戏。但是他经常无法找到快速玩过游戏的办法。现在他有个问题。他要建立一个古城堡,城堡中的路形成一棵树。他要在这棵树的结点上放置最少数目的士兵,使得这些士兵能了望到所有的路。注意,某个士兵在一个结点上时,与该结点相连的所有边将都可以被了望到。

请你编一程序,给定一树,帮Bob计算出他需要放置最少的士兵。

Input Format

输入文件中数据表示一棵树,描述如下: 第一行 N,表示树中结点的数目。 第二行至第N+1行,每行描述每个结点信息,依次为:该结点标号i,k(后面有k条边与结点I相连),接下来k个数,分别是每条边的另一个结点标号r1,r2,...,rk。 对于一个n(0<n<=1500)个结点的树,结点标号在0到n-1之间,在输入文件中每条边只出现一次。

Output Format

输出文件仅包含一个数,为所求的最少的士兵数目。

Sample Input

  1. 4
  2. 0 1 1
  3. 1 2 2 3
  4. 2 0
  5. 3 0

Sample Output

  1. 1

解析

在树形图求解最优化问题,很明显就是一道树形DP的模板题。

我们根据树形\(DP\)通常设置状态的套路来设计这道题的状态:\(f[i][0/1]\)代表以\(i\)为根的子树中的最小士兵数,\(1\)代表节点i放了士兵,\(0\)代表节点i没放士兵。

对于状态的转移,我们可以分两种情况讨论:

1.节点\(i\)放一个士兵,节点\(i\)的子节点可以放士兵,也可以不放士兵

2.节点\(i\)不放士兵,节点i的各个子节点都必须放士兵

那么所对应的状态转移方程就是:

\[1.f[i][1]=\sum_{j \in son(i)}min\{f[j][0],f[j][1]\}+1
\\2.f[i][0]=\sum_{j \in son(i)}f[j][1]
\]

注意到题中没有明确的树根的指明,所以我们只要随便找一个入度为0的点当做树根执行记忆化搜索即可。

\(Code:\)

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N=1500+30;
  4. int n,f[N][2],ans=0x3f3f3f3f,vis[N];vector < int >Link[N];
  5. inline void input(void)
  6. {
  7. scanf("%d",&n);
  8. for(int i=1;i<=n;i++)
  9. {
  10. int index,num,temp;
  11. scanf("%d%d",&index,&num);
  12. for(int j=1;j<=num;j++)
  13. {
  14. scanf("%d",&temp);
  15. Link[index].push_back(temp);
  16. vis[temp]=1;
  17. }
  18. }
  19. }
  20. inline void dp(int root)
  21. {
  22. f[root][1]=1;
  23. f[root][0]=0;
  24. for(int i=0;i<Link[root].size();i++)
  25. {
  26. int Son=Link[root][i];
  27. dp(Son);
  28. f[root][0]+=f[Son][1];
  29. f[root][1]+=min(f[Son][0],f[Son][1]);
  30. }
  31. return;
  32. }
  33. int main(void)
  34. {
  35. freopen("strategi.in","r",stdin);
  36. freopen("strategi.out","w",stdout);
  37. input();
  38. int root;
  39. for(int i=0;i<n;i++)
  40. {
  41. if(!vis[i])
  42. {
  43. root=i;
  44. break;
  45. }
  46. }
  47. dp(root);
  48. printf("%d\n",min(f[root][0],f[root][1]));
  49. }

最大利润(SMOJ1782)

Description

政府邀请了你在火车站开饭店,但不允许同时在两个相连接的火车站开。

任意两个火车站有且只有一条路径,每个火车站最多有50个和它相连接的火车站。

告诉你每个火车站的利润,问你可以获得的最大利润为多少。

Input Format

第一行输入整数N(<=100000),表示有N个火车站,分别用1,2,...,N来编号。

接下来N行,每行一个整数表示每个站点的利润,接下来N-1行描述火车站网络,每行两个整数,表示相连接的两个站点。

Output Format

输出一个整数表示可以获得的最大利润

Sample Input

  1. 6
  2. 10
  3. 20
  4. 25
  5. 40
  6. 30
  7. 30
  8. 4 5
  9. 1 3
  10. 3 4
  11. 2 3
  12. 6 4

Sample Output

  1. 90

解析

这道题和上一道题很像,都是很明显的树形\(DP\)。但是两道题有不同之处:上一题是覆盖相邻的边,但这题是覆盖相邻的点。上一题是必须全部覆盖,这一题是可以不全部覆盖,但不能重叠。我们仍然可以设\(f[i][0/1]\)代表以\(i\)为根的子树中的最大利润,\(0\)代表节点i没有开餐馆,\(1\)代表节点\(i\)开了餐馆。

状态的转移就和上一题很相似了:

1.若节点\(i\)开了餐馆,则它的子节点可以开餐馆,也可以不开

2.若节点\(i\)没开餐馆,则它的子节点都不能开餐馆

状态转移方程:

\[f[i][0]=\sum_{j \in son(i)}max{f[j][1],f[j][0]}
\\f[i][0]=\sum_{j \in son(i)}f[j][0]+a[i]
\]

注意在记忆化搜索的时候需要开一个访问数组标记,避免递归死循环。

\(Code:\)

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N=100000+80;
  4. int n,f[N][2],a[N],vis[N],ans=0;
  5. vector < int > Link[N];
  6. inline void input(void)
  7. {
  8. scanf("%d",&n);
  9. for(int i=1;i<=n;i++)
  10. scanf("%d",&a[i]);
  11. for(int i=1;i<n;i++)
  12. {
  13. int u,v;
  14. scanf("%d%d",&u,&v);
  15. Link[u].push_back(v);
  16. Link[v].push_back(u);
  17. }
  18. }
  19. inline void dp(int root)
  20. {
  21. f[root][0]=0;
  22. f[root][1]=a[root];
  23. for(int i=0;i<Link[root].size();i++)
  24. {
  25. int Son=Link[root][i];
  26. if(vis[Son])continue;
  27. vis[Son]=1;
  28. dp(Son);
  29. f[root][0]+=max(f[Son][1],f[Son][0]);
  30. f[root][1]+=f[Son][0];
  31. }
  32. return;
  33. }
  34. int main(void)
  35. {
  36. freopen("profit.in","r",stdin);
  37. freopen("profit.out","w",stdout);
  38. input();
  39. memset(f,0x00,sizeof f);
  40. memset(vis,0x00,sizeof vis);
  41. vis[1]=1;
  42. dp(1);
  43. printf("%d\n",max(f[1][1],f[1][0]));
  44. }

<后记>

『战略游戏 最大利润 树形DP』的更多相关文章

  1. 『没有上司的舞会 树形DP』

    树形DP入门 有些时候,我们需要在树形结构上进行动态规划来求解最优解. 例如,给定一颗\(N\)个节点的树(通常是无根树,即有\(N-1\)条无向边),我们可以选择任意节点作为根节点从而定义出每一颗子 ...

  2. 『土地征用 Land Acquisition 斜率优化DP』

    斜率优化DP的综合运用,对斜率优化的新理解. 详细介绍见『玩具装箱TOY 斜率优化DP』 土地征用 Land Acquisition(USACO08MAR) Description Farmer Jo ...

  3. 『大 树形dp』

    大 Description 滑稽树上滑稽果,滑稽树下你和我,滑稽树前做游戏,滑稽多又多.树上有 n 个节点,它们构成了一棵树,每个节点都有一个滑稽值. 一个大的连通块是指其中最大滑稽值和最小滑稽值之差 ...

  4. 『You Are Given a Tree 整体分治 树形dp』

    You Are Given a Tree Description A tree is an undirected graph with exactly one simple path between ...

  5. 『快乐链覆盖 树形dp』

    快乐链覆盖 Description 给定一棵 n 个点的树,你需要找至多 k 条互不相交的路径,使得它们的长度之和最大 定义两条路径是相交的:当且仅当存在至少一个点,使得这个点在两条路径中都出现 定义 ...

  6. 『kamp 树形dp』

    kamp Description jz 市的云台山是个很美丽的景区,小 x 暑期到云台山打工,他的任务是开景区的大巴. 云台山景区有 N 个景点,这 N 个景点由 N-1 条道路连接而成,我们保证这 ...

  7. 『树上匹配 树形dp』

    树上匹配 Description 懒惰的温温今天上班也在偷懒.盯着窗外发呆的温温发现,透过窗户正巧能看到一棵 n 个节点的树.一棵 n 个节点的树包含 n-1 条边,且 n 个节点是联通的.树上两点之 ...

  8. 『最短Hamilton路径 状态压缩DP』

    状压DP入门 最短Hamilton路径 Description 给定一张 n(n≤20) 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 的最短Hamilton路径. Hamil ...

  9. 『玩具装箱TOY 斜率优化DP』

    玩具装箱TOY(HNOI2008) Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊 ...

随机推荐

  1. JVM调优入门之初探

    JVM:程序计数器,jvm栈,本地方法栈,堆,方法区 JVM:虚拟机内存又分有:年轻代(eden,servivor s0,servivor s1),年老代(tenured),永久代() 问题1:如何查 ...

  2. Linux之环境搭建(一)

    四大系统比较 Mac OS是苹果机专用系统,是基于Unix内核的图形化操作系统,因此Unix相当于父亲,Linux和Mac OS是对兄弟. CentOS是从Redhat源代码编译重新发布版.CentO ...

  3. 七牛云音频转码准备工作之如何创建音视频处理私有队列pipeline

    如何创建音视频处理私有队列 最近更新时间:2017-08-28 15:54:45 在七牛进行音视频处理,推荐使用私有队列(pipeline). 创建私有队列方法如下: 第一步 登录七牛开发者平台 ht ...

  4. 引用Excel控件时,无法嵌入互操作类型“Microsoft.Office.Interop.Excel.ApplicationClass”请改用适用的接口

    类型Microsoft.Office.Interop.Excel.ApplicationClass未定义构造函数 无法嵌入互操作类型“Microsoft.Office.Interop.Excel.Ap ...

  5. javascript中的函数节流和函数去抖

    带着问题去尝试 首先我们要知道为什么要用到函数节流和函数去抖?我们带着以下的疑问来进行分析! 1.比如搜索框,你会用到什么事件(change.blur.keyup等)?去做什么效果?2.再比如scro ...

  6. 微信小程序开发---视图层(View)

    WXML WXML能力: 数据绑定 列表渲染 条件渲染 模板 事件 数据绑定 数据绑定使用 Mustache 语法(双大括号)将变量包起来,可作用于内容,组件属性(需要在双引号之内),控制属性(需要在 ...

  7. NFS 系统搭建 - 成功

    NFS是Network File System的缩写,即文件系统.客户端通过挂载的方式将NFS服务器端共享的数据目录挂载到本地目录下. 工作流程 1.由程序在NFS客户端发起存取文件的请求,客户端本地 ...

  8. js生成自定义随机数方法

    function getRandom() { var chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', ...

  9. Delphi 开发手机 App 与其他工具之间的比较分析

    写在前头 关于各种手机App开发的工具,从2010年前后到现在已经在很多不同的场合介绍过,在元智大学.中台科技大学.德霖科技大学等不同学校的讲座.课程当中,都有类似的主题,所以对我来说,这个主题属于驾 ...

  10. 为什么 web 开发人员需要迁移到. NET Core, 并使用 ASP.NET Core MVC 构建 web 和 webservice/API

    2018 .NET开发者调查报告: .NET Core 是怎么样的状态,这里我们看到了还有非常多的.net开发人员还在观望,本文给大家一个建议.这仅代表我的个人意见, 我有充分的理由推荐.net 程序 ...