树形DP

合集下载

dp入门

dp入门

dp[j] = max(dp[j], dp[j - c[i]] + v[i]);
}
}
i\j
j=0
i=0
0
j=1 j=2 j=3 j=4 j=5 j=6
0
00000i=10
3
6
9
12 15 18
i=2
0
3
6
10
13 16 20
17
多重背包
有n种物品,每种最多可以取x[i]个,每个物品有大小和价值,问总大小不超过m的情况下能取到最大的 价值是多少 代码如下: for (int i = 1; i <= n; ++i) {
} } 注意此时j一定是倒序产生
16
完全背包
有n种物品,每种最多可以取无数个,每个物品有大小和价值,问总大小不超过m的情况下能取到最大 的价值是多少
01背包中第二维改成正向即可:
for (int i = 1; i <= n; ++i) {
for (int j = c[i]; j <= m; ++j) {
}
10
数字三角形
线性DP解法 for(int i=m-1;i>0;i--) {
for(int j=0;j<=i;j++) { a[i-1][j]+=max(a[i][j],a[i][j+1]);
} }
11
数字三角形
暴力递归搜索解法: int dfs(int i, int j) {
if (i == n) return a[i][j]; return max(dfs(i+1,j), dfs(i+1,j+1)) + a[i][j]; }

树形数位动态规划_黄哲威

树形数位动态规划_黄哲威

花神的数论题
» 用用sum(i)表示数i二二进制表示下1的个数。 » 问sum(1)~sum(n)这n个数的乘积对
1000000007取模的结果。 » n<=10^15
» 这使得NOIp中看似没有单独讨论数位DP的必 要。
» 但事实上这种方方法还是有或多或少的细节,所以 大大家还是把数位DP看成一一类特殊的DP。初学者 一一般比比较难以一一次写对,但好好对拍就没事了了。
WINDY数
» windy定义了了一一种windy数。不不含前导零且相 邻两个数字之差至至少为2的正整数被称为 windy数。 windy想知道,在A和B之间,包括 A和B,总共有多少个windy数?将答案对 1000000007取模。
树形与数位动态规划
2019年年1月月26日日
⻩黄哲威 hzwer
北北京大大学16级计算机科学
第三节目目标
• 一一些树形dp补充
• 数位dp介绍
• 数位dp练习
NOIP2014 联合权值
» 无无向连通图 G 有 n 个点,n-1 条边。点从 1 到 n 依次编 号,编号为 i 的点的权值为 Wi,每条边的⻓长度均为 1。
» 但是这题数据范围有10^9,(sqrt(B)),这里里里取60000左右。然后预处理理出所有 F[k*S], k=1,2,...
» 这样读入入询问后,找到离B最近的一一个k*S,从F[k*S]开始暴暴力力力计算F[B]。 例例如B=60111,那么因为已经算出了了F[60000],暴暴力力力for i=60001 ... 60111 判断每个i是否是windy数即可。
• 在n个点的点权树上选两条不不相交的路路径,使
路路径上的点权和最大大
• n <= 100000

CA一句话题解

CA一句话题解
1543:同JSOI2008最小生成树计数.
1563:四边形不等式推出决策单调,二分决策点.
1568:李超线段树.
1588:权值平衡树.
1798:线段树双标记.但是我是拿LCT写的.
1800:暴力
1821:二分答案+并查集
1853:爆搜
1857:三分套三分.
1875:矩乘优化DP
达式..
2213:DP乱搞一下.附核心代码
for (int i=2;i&lt;=n;++i) ch[i]=getchar(),maxn=max(maxn,ch[i]-&#39;a&#39;);
for (int i=1;i&lt;=n;++i)
{
2222:似乎数据有问题还是什么?面向数据了一波.
2223:主席树
2229:GHTree
2241:暴力枚举答案然后检测,检测时候需要特技,感觉理论复杂度并不对但是过了
2243:链剖或者LCT,我写的链剖
2244:cdq分治做三维偏序的DP,答案实际上可能非常大会爆…但是出题人十分懒惰没管那样的数据,所以double就过了
2151:堆+贪心
2154:莫比乌斯反演,有很多种公式化法,我的好像是比较傻逼的那种..
2157:LCT,随便打标记
2163:直接最小割过了,其实应该转对偶图然后最短路才对.
2186:考察线性的逆元求法.
2190:反演分析一下,最后却发现答案是个跟phi有关的表
1007:半平面交
1008:组合数学,需要高精
1010:斜率优化/四边形不等式推决策单调性

最大独立集

最大独立集

最大独立集最大独立集 1最大独立集 1题目描述某大学有N个职员,编号为1~N。

他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。

现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri,但是呢,如果某个职员的上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。

所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。

输入格式第一行一个整数N。

(1<=N<=6000)接下来N行,第i+1行表示i号职员的快乐指数Ri。

(-128<=Ri<=127)接下来N-1行,每行输入一对整数L,K。

表示K是L的直接上司。

最后一行输入0 0输出格式输出最大的快乐指数。

输入输出样例输入 #1711111111 32 36 47 44 53 50 0输出 #15方法:树形dp这是典型的最大独立集2。

(这个水问题有这么高大上的雅号)直接树形dp即可。

\(dp[x][0/1]\)表示选/不选第x个点的最大快乐度。

代码:#include<bits/stdc++.h>using namespace std;int dp[10010][2],n,A[10010];vector<int> G[10010];void DFS(int x,int fa){dp[x][1]=A[x];for(int i=0;i<G[x].size();i++){int t=G[x][i];if(t==fa)continue;DFS(t,x);dp[x][0]+=max(dp[t][0],dp[t][1]);dp[x][1]+=dp[t][0];}}int main(){scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&A[i]);for(int i=1;i<=n-1;i++){int x,y;scanf("%d %d",&x,&y);G[x].push_back(y);G[y].push_back(x);}DFS(1,0);cout<<max(dp[1][0],dp[1][1]);return 0;}最大独立集 2基环树,也是环套树,简单地讲就是树上在加一条边。

动态规划基础、进阶与优化

动态规划基础、进阶与优化

山东师大附中陈键飞前言自古以来就是NOIP的重要考察内容,在联赛中占的分量大。

对选手能力有一定要求,需要能够熟练地建立动态规划模型。

需要大量做题,初学者不易掌握其思想。

目录基础:基本概念背包问题——一类典型应用 进阶:更多的问题树形DP状态压缩优化:减少状态数目减少状态转移(决策)时间基本概念最长上升子序列状态:f[i]能完全地表示出问题某个或某些本质相同的形态决策:f[i]=min(f[j]+1)状态由哪个状态转移得到阶段:每个i前面的阶段决定后面的阶段,后面的阶段由前面的状态转移得到基本概念石子合并状态f[i,j]决策f[i,j]=min(f[i,k]+f[k+1,j])+w[i,j] 阶段j-i (区间大小)基本概念无后效性后面阶段的状态只受前面阶段的状态的影响 对于任意两个状态,只能单向的进行转移基本概念拓扑图(有向无环图)无后效性f[i]=min(f[j])+1基本概念 非拓扑图(可能有环) 有后效性a →b →c ?b →c →a ?a bc 51111基本概念最优子问题问题最优,只需子问题最优,与到达子问题的路径无关3 5 24 6f(5)最优,只需f(4)最优,与f(4)是怎么到达的无关与路线具体是3 4 6还是2 4 6无关基本概念最优子问题输出1~n中∑(A(i,p[i]))最大的排列f(i)表示用1~n组成的长度为i的序列? 与到达子问题的路径有关!1 4 3 →6 ?4 2 3 →6 ?基本概念无后效性、最优子问题是否能满足与状态的表示,状态的转移,阶段的划分有关背包问题——一类典型应用 给定n个货币,面值各不相同,问能否凑出m元钱f[i,j]表示前i个货币能否凑出j元f[i,j] = f[i-1,j] (不选j)or f[i-1,j-w[i]](选j)背包问题——一类典型应用 给定n种货币,每种无限多个,面值各不相同,问能否凑出m元钱f[i,j]表示前i种货币能否凑出j元f[i,j]=f[i-1,j] or f[i,j-w[i]]背包问题——一类典型应用 给定n种货币,第i种有A i个,面值W i,问能否凑出m 元钱将每种货币i拆成A i个价值为W i的货币O(m∑A i)将每种货币i拆成价值为W i,2W i,4W i,8W i……的货币O(m∑log A i)单调队列O(mn) ,暂时跳过背包问题——一类典型应用 给定n种货币分为k组,每组只能选一个,问能否凑出m元f[i,j,k]表示用前1~i-1组和第i组的前j个能否凑出k元。

acm中dp问题简单入门讲解

acm中dp问题简单入门讲解

ACM暑期集训报告院系:专业:年级:学号:姓名:日期:西南交通大学目录目录.................................................. 错误!未定义书签。

第1章动态计划(dp) ............................ 错误!未定义书签。

简介.................................................... 错误!未定义书签。

教师内容................................................ 错误!未定义书签。

大体dp——背包问题..................................... 错误!未定义书签。

假设干经典dp及常见优化.................................. 错误!未定义书签。

类似题目................................................. 错误!未定义书签。

参考文献........................................... 错误!未定义书签。

附录1 暑期集训心得体会............................. 错误!未定义书签。

第1章动态计划(dp)(题目采纳2号黑体居中,下空1行)简介(题目采纳四号黑体,正文内容采纳小四号字体,倍行距)在解决问题的时候咱们常常碰到这种问题:在多种方式的操作下咱们如何取得一个最优的方式让咱们取得中意的结果。

这时咱们大多人的思想确实是贪婪。

不错贪婪确实是一个不错的算法,第一他简单容易想到,咱们在操作起来也比较容易。

此刻我推荐几道咱们oj上的贪婪算法的题:soj1562药品运输 soj1585 Climbing mountain。

为了引入动归算法我先拿药品运输这道题简单说一下贪婪算法。

例如1:药品运输(题目采纳小四号Times New Roman字体)Description大地震后,某灾区急需一批药品,此刻有N种药品需要运往灾区,而咱们的运输能力有限,此刻仅有M辆运输车用来运输这批药品,已知不同的药品对灾区具有不同的作用(“作用”用一个整数表示其大小),不同的药品需要的运输力(必要的车辆运载力)不同,而不同的车辆也具有不同的运输力。

dp有哪些种类

dp有哪些种类

dp有哪些种类dp有哪些种类⼀、总结⼀句话总结:⼆、dp动态规划分类详解动态规划⼀直是ACM竞赛中的重点,同时⼜是难点,因为该时间效率⾼,代码量少,多元性强,主要考察思维能⼒、建模抽象能⼒、灵活度。

******************************************************************************************动态规划(:Dynamic programming,DP)是⼀种在、和中使⽤的,通过把原问题分解为相对简单的⼦问题的⽅式求解复杂问题的⽅法。

动态规划常常适⽤于有和性质的问题,动态规划⽅法所耗时间往往远少于朴素解法。

动态规划背后的基本思想⾮常简单。

⼤致上,若要解⼀个给定问题,我们需要解其不同部分(即⼦问题),再合并⼦问题的解以得出原问题的解。

通常许多⼦问题⾮常相似,为此动态规划法试图仅仅解决每个⼦问题⼀次,从⽽减少计算量:⼀旦某个给定⼦问题的解已经算出,则将其存储,以便下次需要同⼀个⼦问题解之时直接查表。

这种做法在重复⼦问题的数⽬关于输⼊的规模呈时特别有⽤。

动态规划问题满⾜三⼤重要性质最优⼦结构性质:如果问题的最优解所包含的⼦问题的解也是最优的,我们就称该问题具有最优⼦结构性质(即满⾜最优化原理)。

最优⼦结构性质为动态规划算法解决问题提供了重要线索。

⼦问题重叠性质:⼦问题重叠性质是指在⽤递归算法⾃顶向下对问题进⾏求解时,每次产⽣的⼦问题并不总是新问题,有些⼦问题会被重复计算多次。

动态规划算法正是利⽤了这种⼦问题的重叠性质,对每⼀个⼦问题只计算⼀次,然后将其计算结果保存在⼀个表格中,当再次需要计算已经计算过的⼦问题时,只是在表格中简单地查看⼀下结果,从⽽获得较⾼的效率。

:将各阶段按照⼀定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态⽆法直接影响它未来的决策,⽽只能通过当前的这个状态。

换句话说,每个状态都是过去历史的⼀个完整总结。

NOIP的DP总结之DP类型

NOIP的DP总结之DP类型
代码:
procedure MultiplePack(cost,weight,amount)
if cost*amount>=V
CompletePack(cost,weight)
return
integer k=1
while k<amount
ZeroOnePack(k*cost,k*weight)
amount=amount-k
f[j*v+k]:=b[l]+j*w; //用队列头的值更新f[j*v+k]
end;
end;
end;
writeln(f[m]);
end.
题目:砝码秤重,tyvj1086,zoj2156,poj2392,hdu1085
Poj1014,divide(见dp2)
二维费用背包
就是限制条件多了一个,变成了二维容量,从而状态多了一维而已。
题目:hdu3236,打包(见dpset)poj2184
分组背包
有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。这些物品被划分为若干组,每组中的物品互相冲突,最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
这个问题变成了每组物品有若干种策略:是选择本组的某一件,还是一件都不选。也就是说设f[k][v]表示前k组物品花费费用v能取得的最大权值,则有:f[k][v]
for i:=1 to n do
begin
read(v,w,c); //读入当前物品:v为物品体积、w为物品价值、c为物品可用次数
if m div v<c k:=0 to v-1 do //把所有的体积按除以v的余数划分为0~v-1

信息学奥赛——树型动态规划的实例分析

信息学奥赛——树型动态规划的实例分析

信息学奥赛——树型动态规划的实例分析树型动态规划(Tree Dynamic Programming)是信息学奥赛中常用的一种算法思想,在解决一些与树相关的问题时非常有效。

本文将通过一个具体的实例对树型动态规划进行详细分析。

假设有一棵有根树,每个节点上都有一个非负整数权值,并且每个节点下都可能有若干个子节点。

现在要求选择一些节点,使得选中的节点的权值之和尽可能大,但是不能选择相邻的节点。

我们需要设计一个算法来解决这个问题。

首先,我们可以观察到如果一个节点被选中,那么它的子节点就不能被选中。

于是,我们可以定义一个动态规划的状态dp[i]表示以节点i为根的子树中选择节点的最大权值之和。

对于根节点,我们有两种情况:1. 根节点i被选择,那么它的子节点就不能被选择。

所以dp[i] = sum(dp[j]),其中j表示i的所有子节点。

2. 根节点i不被选择,那么它的所有子节点都可以被选择。

所以dp[i] = sum(max(dp[j], dp[k])),其中j和k分别表示i的所有孩子节点的子节点。

通过对根节点的两种状态的分析,我们可以得到一个递推关系:dp[i] = max(sum(dp[j]), sum(max(dp[k], dp[l]))),其中j表示i的所有子节点,k和l分别表示i的所有孩子节点的子节点。

接下来,我们需要设计一个合适的递归算法来计算dp[i]。

我们可以使用深度优先(DFS)的方式来处理每个节点,实现递归的过程。

具体的伪代码如下:```DFS(i):visit[i] = truefor j in i的所有子节点:if visit[j] == false:DFS(j)dp[i] += dp[j]for k in i的所有孩子节点:for l in k的所有子节点:dp[i] += max(dp[k], dp[l])```最后,我们只需要调用DFS函数以根节点为参数,可以得到整棵树的最优解。

搜索、DP

搜索、DP
题目描述 Description 如图所示的数字三角形,从顶部出发,在每 一结点可以选择向左走或得向右走,一直走 到底层,要求找出一条路径,使路径上的值 最大。 输入描述 Input Description
样例输入 Sample Input 5 13 11 8 12 7 26 6 14 15 8 12 7 13 24 11 样例输出 Sample Output 86
区间型动态规划——石子合并 (Wikioi 1048)
初始阶段:就是s[1,1],s[2,1],s[3,1],s[4,1],s[5,1],s[6,1],因为一开始还没有合并,所以这 些值应该全部为0。
第二阶段:两两合并过程如下,其中sum(i,j)表示从i开始数j个数的和
如:s[1,2]=s[1,1]+s[2,1]+sum(1,2)。 第三阶段:三三合并可以拆成两两合并,拆分方法有两种,前两个为一组或后两个为一组
例题
线性动态规划——导弹拦截 (VIJOS P1303)
描述 某国为了防御敌国的导弹袭击,研发出一种导弹拦截系统。但是这种导弹拦截系统有一个 缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发 的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试验阶段,所以只有一套系 统,因此有可能不能拦截所有的导弹。 输入格式 输入数据只有一行,该行包含若干个数据,之间用半角逗号隔开,表示导弹依次飞来的高 度(导弹最多有 20 枚,其高度为不大于 30000 的正整数)。 输出格式
搜索、动态规划
搜索
搜索

盲目搜索算法

深度优先搜索(DFS)
广度优先搜索(BFS) 迭代加深搜索(Iterative Deepening)

POJ分类

POJ分类

POJ上一些题目在http://162.105.81.202/course/problemSolving/可以找到解题报告。

《算法艺术与信息学竞赛》的习题提示在网上可搜到一.动态规划参考资料:刘汝佳《算法艺术与信息学竞赛》《算法导论》推荐题目:/JudgeOnline/problem?id=1141简单/JudgeOnline/problem?id=2288中等,经典TSP问题/JudgeOnline/problem?id=2411中等,状态压缩DP/JudgeOnline/problem?id=1112中等/JudgeOnline/problem?id=1848中等,树形DP。

可参考《算法艺术与信息学竞赛》动态规划一节的树状模型/show_problem.php?pid=1234中等,《算法艺术与信息学竞赛》中的习题/JudgeOnline/problem?id=1947中等,《算法艺术与信息学竞赛》中的习题/JudgeOnline/problem?id=1946中等,《算法艺术与信息学竞赛》中的习题/JudgeOnline/problem?id=1737中等,递推/JudgeOnline/problem?id=1821中等,需要减少冗余计算/show_problem.php?pid=2561中等,四边形不等式的简单应用/JudgeOnline/problem?id=1038较难,状态压缩DP,《算法艺术与信息学竞赛》中有解答/JudgeOnline/problem?id=1390较难,《算法艺术与信息学竞赛》中有解答/JudgeOnline/problem?id=3017较难,需要配合数据结构优化(我的题目^_^)/JudgeOnline/problem?id=1682较难,写起来比较麻烦/JudgeOnline/problem?id=2047较难/JudgeOnline/problem?id=2152难,树形DP/JudgeOnline/problem?id=3028难,状态压缩DP,题目很有意思/JudgeOnline/problem?id=3124难/JudgeOnline/problem?id=2915非常难二.搜索参考资料:刘汝佳《算法艺术与信息学竞赛》推荐题目:/JudgeOnline/problem?id=1011简单,深搜入门题/JudgeOnline/problem?id=1324中等,广搜/JudgeOnline/problem?id=2044中等,广搜/JudgeOnline/problem?id=2286较难,广搜/JudgeOnline/problem?id=1945难,IDA*,迭代加深搜索,需要较好的启发函数/JudgeOnline/problem?id=2449难,可重复K最短路,A*。

《算法竞赛进阶指南》0x54树形DPPOJ3585积蓄程度

《算法竞赛进阶指南》0x54树形DPPOJ3585积蓄程度

《算法竞赛进阶指南》0x54树形DPPOJ3585积蓄程度给定⼀棵树,边上⾯代表的是流量,可以选定⼀个点作为源点,⼀个点作为汇点,汇点的出量⽆限,源点的⼊量⽆限,问选择哪⼀个点能使得树中这个点为源点的流量最⼤。

采⽤的算法是⼆次扫描与换根法,第⼀次扫描的时候选择⼀个root⾃底向上算出d的值,也就是从这个点出发向下的最⼤流量,⼀次扫描后root结点的流量是确定的,复制到f[root]中,接下来对⾃顶向下更新⼦树的f数组的值。

更新的时候⽤上已经是真实f的⽗节点的f数组值以及当前点的d数组的值。

注意在⽗节点和⼦节点是叶⼦节点的时候要单独计算f函数的值,因为实际上叶⼦结点计算的d数组值是0,但是实际上应该是inf,所以在d数组是⾮真实的时候要单独计算。

代码:#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 200010;const int inf=0x3f3f3f3f;int n;int head[maxn],nxt[maxn<<1],len[maxn<<1],ver[maxn<<1];int f[maxn],d[maxn];int deg[maxn];int cnt=0;void addedge(int a,int b,int c){ver[++cnt]=b;len[cnt]=c;nxt[cnt]=head[a];head[a]=cnt;}void dfs_d(int u,int fa){d[u]=0;for(int i=head[u];i;i=nxt[i]){int v=ver[i];int w=len[i];if(v==fa)continue;dfs_d(v,u);if(deg[v]==1)d[u]+=w;else d[u]+=min(d[v],w);}}void dfs_f(int u,int fa){//u及以上的部分f数组已经计算完毕,//通过⽗节点更新⼦节点的信息for(int i=head[u];i;i=nxt[i]){int v=ver[i];int w=len[i];if(v==fa)continue;if(deg[u]==1)f[v]=d[v]+w;//⽗节点是叶⼦结点else if(deg[v]==1)f[v]=min(f[u]-w,w);else f[v]=d[v]+min(f[u]-min(d[v],w),w);dfs_f(v,u);//计算以v为根节点的⼦树的所有f}}int main(){int T;scanf("%d",&T);while(T--){cnt=0;scanf("%d",&n);memset(head,0,sizeof(head));memset(deg,0,sizeof deg);for(int i=0;i<n-1;i++){int a,b,c;scanf("%d%d%d",&a,&b,&c);addedge(a,b,c);addedge(b,a,c);deg[a]++,deg[b]++;}memset(d,0,sizeof(d));dfs_d(1,-1);//算出d数组f[1]=d[1];dfs_f(1,-1);int res=0;for(int i=1;i<=n;i++)res=max(res,f[i]);printf("%d\n",res);}return0;}。

Codeforces1179D树形DP斜率优化

Codeforces1179D树形DP斜率优化

Codeforces1179D树形DP斜率优化题意:给你⼀颗树,你可以在树上添加⼀条边,问添加⼀条边之后的简单路径最多有多少条?简单路径是指路径中的点只没有重复。

思路:添加⼀条边之后,树变成了基环树。

容易发现,以基环上的点为根的⼦树的点中的简单路径没有增加。

所以,问题相当于转化为找⼀个基环,使得以基环上的点为根的⼦树Σ(i从1到n) sz[i] * (sz[i] - 1) / 2最⼩。

我们把式⼦转化⼀下变成求(sz[i]的平⽅和 - n) / 2。

相当于我们需要求sz[i]的平⽅和。

但是,我们并不知道哪个是基环,怎么求sz呢?我们发现⼀个性质:添加的边连接的两点⼀定是树中度数为1的点,否则,我们⼀定可以缩⼩平⽅和。

所以,根据这个性质,我们可以进⾏树形dp。

设dp[i]为以i为根的⼦树中,选择从i到⼦树中的某个叶⼦节点的路径为基环上的点,可以获得的最⼩的平⽅和。

dp[i] = min(dp[son] + (sz[i] - sz[son]) ^ 2)。

我们假设选择的基环是u -> lca(u, v) -> v ,假设fu为u到lca(u, v)的路径中lca(u, v)的前⾯⼀个节点,fv同理,那么平⽅和为ans = dp[fu] + dp[fv] + (n - sz[fu] - sz[fv]) ^ 2。

所以,我们在深搜的时候,找到所有孩⼦的dp值和sz,枚举是哪两个孩⼦来更新平⽅和,这样最坏情况是O(n ^ 2)的,会超时。

发现状态转移⽅程中有fu和fv的乘积项,我们可以考虑斜率优化。

把⽅程移项: dp[fv] = 2 * (n - sz[fu]) * sz[fv] + (ans - dp[fu] - 2 * n * sz[fu])。

那么相当于是以sz[fv]为横坐标,dp[fv]为纵坐标,斜率为2 * (n - sz[fu])的直线,要ans最⼩,需要截距最⼩。

我们把sz从⼩到⼤排序,⽤单调队列维护⼀个下凸包,之后在单调队列⾥⼆分即可。

DP算法总结

DP算法总结

1. 资源问题1-----机器分配问题f[i,j]:=max(f[i-1,k]+w[i,j-k]);2. 资源问题2------01背包问题f[i,j]:=max(f[i-1,j-v[i]]+w[i],f[i-1,j]);3. 线性动态规划1-----朴素最长非降子序列f[i]:=max{f[j]+1}4. 剖分问题1-----石子合并f[i,j]:=min(f[i,k]+f[k+1,j]+sum[i,j]);5. 剖分问题2-----多边形剖分f[i,j]:=min(f[i,k]+f[k,j]+a[k]*a[j]*a[i]);6. 剖分问题3------乘积最大f[i,j]:=max(f[k,j-1]*mult[k,i]);7. 资源问题3-----系统可靠性(完全背包)f[i,j]:=max{f[i-1,j-c[i]*k]*P[I,x]};8. 贪心的动态规划1-----快餐问题f[i,j,k]:=max{f[i-1,j',k']+(T[i]-(j-j')*p1-(k-k')*p2) div p3};9. 贪心的动态规划2-----过河f[i]=min{{f(i-k)} (not stone[i]){f(i-k)}+1} (stone[i]); +贪心压缩状态10. 剖分问题4-----多边形-讨论的动态规划F[i,j]:=max{正正f[I,k]*f[k+1,j];负负g[I,k]*f[k+1,j];正负g[I,k]*f[k+1,j];负正f[I,k]*g[k+1,j];} g为min11. 树型动态规划1-----加分二叉树(从两侧到根结点模型)F[i,j]:=max{f[i,k-1]*f[k+1,j]+c[k]};12. 树型动态规划2-----选课(多叉树转二叉树,自顶向下模型)f[i,j]表示以i为根节点选j门功课得到的最大学分f[i,j]:=max{f[t[i].l,k]+f[t[i].r,j-k-1]+c[i]};13. 计数问题1-----砝码称重f[f[0]+1]=f[j]+k*w[j];(1<=i<=n; 1<=j<=f[0]; 1<=k<=a[i];)14. 递推天地1------核电站问题f[-1]:=1; f[0]:=1;f[i]:=2*f[i-1]-f[i-1-m];15. 递推天地2------数的划分f[i,j]:=f[i-j,j]+f[i-1,j-1];16. 最大子矩阵1-----一最大01子矩阵f[i,j]:=min(f[i-1,j],v[i,j-1],v[i-1,j-1])+1;ans:=maxvalue(f);17. 判定性问题1-----能否被4整除g[1,0]:=true; g[1,1]:=false; g[1,2]:=false; g[1,3]:=false; g[i,j]:=g[i-1,k] and ((k+a[i,p]) mod 4 = j)18. 判定性问题2-----能否被k整除f[i,j±n[i] mod k]:=f[i-1,j]; -k<=j<=k; 1<=i<=n20. 线型动态规划2-----方块消除游戏f[i,i-1,0]:=0f[i,j,k]:=max{f[i,j-1,0]+sqr(len(j)+k), //dof[i,p,k+len[j]]+f[p+1,j-1,0] //not do}; ans:=f[1,m,0];21. 线型动态规划3-----最长公共子串,LCS问题f[i,j]=0 (i=0)&(j=0);f[i-1,j-1]+1 (i>0,j>0,x[i]=y[j]);max{f[i,j-1]+f[i-1,j]}} (i>0,j>0,x[i]<>y[j]);22. 最大子矩阵2-----最大带权01子矩阵O(n^2*m)枚举行的起始,压缩进数列,求最大字段和,遇0则清零23. 资源问题4-----装箱问题(判定性01背包)f[j]:=(f[j] or f[j-v[i]]);24. 数字三角形1-----朴素の数字三角形f[i,j]:=max(f[i+1,j]+a[I,j],f[i+1,j+1]+a[i,j]);25. 数字三角形2-----晴天小猪历险记之Hill同一阶段上暴力动态规划f[i,j]:=min(f[i,j-1],f[i,j+1],f[i-1,j],f[i-1,j-1])+a[i,j];26. 双向动态规划1数字三角形3-----小胖办证f[i,j]:=max(f[i-1,j]+a[i,j],f[i,j-1]+a[i,j],f[i,j+1]+a[i,j]);27. 数字三角形4-----过河卒//边界初始化f[i,j]:=f[i-1,j]+f[i,j-1];28. 数字三角形5-----朴素的打砖块f[i,j,k]:=max(f[i-1,j-k,p]+sum[i,k],f[i,j,k]);29. 数字三角形6-----优化的打砖块f[i,j,k]:=max{g[i-1,j-k,k-1]+sum[i,k]};30. 线性动态规划3-----打鼹鼠’f[i]:=f[j]+1;(abs(x[i]-x[j])+abs(y[i]-y[j])<=t[i]-t[j]);31. 树形动态规划3-----贪吃的九头龙f[i,j,k]:=min(f[x1,j1,1]+f[x2,j-j1-1,k]+d[k,1]*cost[i,fa[i]]] {Small Head}, f[x1,j1,0]+f[x2,j-j1,k]+d[k,0]*cost[i,fa[i]] {Big Head});f[0,0,k]:=0; f[0,j,k]:=max(j>0)d[i,j]:=1 if (i=1) and (j=1)1 if (i=0) and (j=0) and (M=2)0 else32. 状态压缩动态规划1-----炮兵阵地Max(f[Q*(r+1)+k],g[j]+num[k]);If (map[i] and plan[k]=0) and((plan[P] or plan[q]) and plan[k]=0);33. 递推天地3-----情书抄写员f[i]:=f[i-1]+k*f[i-2];34. 递推天地4-----错位排列f[i]:=(i-1)(f[i-2]+f[i-1]);f[n]:=n*f[n-1]+(-1)^(n-2);35. 递推天地5-----直线分平面最大区域数f[n]:=f[n-1]+n:=n*(n+1) div 2 + 1;36. 递推天地6-----折线分平面最大区域数f[n]:=(n-1)(2*n-1)+2*n;37. 递推天地7-----封闭曲线分平面最大区域数f[n]:=f[n-1]+2*(n-1);:=sqr(n)-n+2;38 递推天地8-----凸多边形分三角形方法数f[n]:=C(2*n-2,n-1) div n;对于k边形f[k]:=C(2*k-4,k-2) div (k-1); //(k>=3)39 递推天地9-----Catalan数列一般形式1,1,2,5,14,42,132f[n]:=C(2k,k) div (k+1);40 递推天地10-----彩灯布置排列组合中的环形染色问题f[n]:=f[n-1]*(m-2)+f[n-2]*(m-1); (f[1]:=m; f[2]:=m(m-1);41 线性动态规划4-----找数线性扫描sum:=f[i]+g[j];(if sum=Aim then getout; if sum<Aim then inc(i) else inc(j);)42 线性动态规划5-----隐形的翅膀min:=min{abs(w[i]/w[j]-gold)};if w[i]/w[j]<gold then inc(i) else inc(j);43 剖分问题5-----最大奖励f[i]:=max(f[i],f[j]+(sum[j]-sum[i])*i-t;44 最短路1-----Floydf[i,j]:=max(f[i,j],f[i,k]+f[k,j]);ans[q[i,j,k]]:=ans[q[i,j,k]]+s[i,q[i,j,k]]*s[q[i,j,k],j]/s[i,j];45 剖分问题6-----小H的小屋F[l,m,n]:=f[l-x,m-1,n-k]+S(x,k);46 计数问题2-----陨石的秘密(排列组合中的计数问题)Ans[l1,l2,l3,D]:=f[l1+1,l2,l3,D+1]-f[l1+1,l2,l3,D];F[l1,l2,l3,D]:=Sigma(f[o,p,q,d-1]*f[l1-o,l2-p,l3-q,d]);47 线性动态规划------合唱队形两次F[i]:=max{f[j]+1}+枚举中央结点48 资源问题------明明的预算方案:加花的动态规划f[i,j]:=max(f[i,j],f[l,j-v[i]-v[fb[i]]-v[fa[i]]]+v[i]*p[i]+v[fb[i]]*p[fb[i]]+v[fa[i]]*p[fa[i]]);49 资源问题-----化工场装箱员50 树形动态规划-----聚会的快乐f[i,2]:=max(f[i,0],f[i,1]);f[i,1]:=sigma(f[t[i]^.son,0]);f[i,0]:=sigma(f[t[i]^.son,3]);51 树形动态规划-----皇宫看守f[i,2]:=max(f[i,0],f[i,1]);f[i,1]:=sigma(f[t[i]^.son,0]);f[i,0]:=sigma(f[t[i]^.son,2]);52 递推天地-----盒子与球f[i,1]:=1;f[i,j]:=j*(f[i-1,j-1]+f[i-1,j]);53 双重动态规划-----有限的基因序列f[i]:=min{f[j]+1}g[c,i,j]:=(g[a,i,j] and g[b,i,j]) or (g[c,i,j]);54 最大子矩阵问题-----居住空间f[i,j,k]:=min(min(min(f[i-1,j,k],f[i,j-1,k]),min(f[i,j,k-1],f[i-1,j-1,k])),min(min(f[i-1,j,k-1],f[i,j-1,k-1] ),f[i-1,j-1,k-1]))+1;55 线性动态规划------日程安排f[i]:=max{f[j]}+P[I]; (e[j]<s[i])56 递推天地------组合数C[i,j]:=C[i-1,j]+C[i-1,j-1];C[i,0]:=157 树形动态规划-----有向树k中值问题F[I,r,k]:=max{max{f[l[i],I,j]+f[r[i],I,k-j-1]},f[f[l[i],r,j]+f[r[i],r,k-j]+w[I,r]]};58 树形动态规划-----CTSC 2001选课F[I,j]:=w[i](if i∈P)+f[l[i],k]+f[r[i],m-k](0≤k≤m)(if l[i]<>0);59 线性动态规划-----多重历史f[i,j]:=sigma{f[i-k,j-1]}(if checked);60 背包问题(+-1背包问题+回溯)-----CEOI1998 Substractf[i,j]:=f[i-1,j-a[i]] or f[i-1,j+a[i]];61 线性动态规划(字符串)-----NOI 2000 古城之谜f[i,1,1]:=min{f[i+length(s),2,1], f[i+length(s),1,1]+1};f[i,1,2]:=min{f[i+length(s),1,2]+words[s],f[i+length(s),1,2]+words[s]};62 线性动态规划-----最少单词个数f[i,j]:=max{f[i,j],f[u-1,j-1]+l};63 线型动态规划-----APIO2007 数据备份状态压缩+剪掉每个阶段j前j*2个状态和j*2+200后的状态贪心动态规划f[i]:=min(g[i-2]+s[i],f[i-1]);64 树形动态规划-----APIO2007 风铃f[i]:=f[l]+f[r]+{1 (if c[l]<c[r])};g[i]:=1(d[l]<>d[r]) 0(d[l]=d[r]);g[l]=g[r]=1 then Halt;65 地图动态规划-----NOI 2005 adv19910F[t,i,j]:=max{f[t-1,i-dx[d[[t]],j-dy[d[k]]]+1],f[t-1,i,j];66 地图动态规划-----优化的NOI 2005 adv19910F[k,i,j]:=max{f[k-1,i,p]+1} j-b[k]<=p<=j;67 目标动态规划-----CEOI98 subtraF[I,j]:=f[I-1,j+a[i]] or f[i-1,j-a[i]];68 目标动态规划----- Vijos 1037搭建双塔问题F[value,delta]:=g[value+a[i],delta+a[i]] or g[value,delta-a[i]];69 树形动态规划-----有线电视网f[i,p]:=max(f[i,p],f[i,p-q]+f[j,q]-map[i,j]);leaves[i]>=p>=l, 1<=q<=p;70 地图动态规划-----vijos某题F[i,j]:=min(f[i-1,j-1],f[i,j-1],f[i-1,j]);71 最大子矩阵问题-----最大字段和问题f[i]:=max(f[i-1]+b[i],b[i]); f[1]:=b[1];72 最大子矩阵问题-----最大子立方体问题枚举一组边i的起始,压缩进矩阵B[I,j]+=a[x,I,j];枚举另外一组边的其实,做最大子矩阵73 括号序列-----线型动态规划f[i,j]:=min(f[i,j],f[i+1,j-1] (s[i]s[j]=”()”or(”[]”)),f[i+1,j+1]+1 (s[j]=”(”or”[” ) , f[i,j-1]+1(s[j]=”)”or”]”);74 棋盘切割-----线型动态规划f[k,x1,y1,x2,y2]=min{min{f[k-1,x1,y1,a,y2]+s[a+1,y1,x2,y2],f[k-1,a+1,y1,x2,y2]+s[x1,y1,a,y2]};75 概率动态规划-----聪聪和可可(NOI2005)x:=p[p[i,j],j];f[I,j]:=(f[x,b[j,k]]+f[x,j])/(l[j]+1)+1;f[I,i]=0;f[x,j]=1;76 概率动态规划-----血缘关系F[A, B]=(f[A0, B]+P[A1, B])/2;f[i,i]=1;f[i,j]=0;(i,j无相同基因)77 线性动态规划-----决斗F[i,j]=(f[i,j] and f[k,j]) and (e[i,k] or e[j,k]); (i<k<j)78 线性动态规划-----舞蹈家F[x,y,k]=min(f[a[k],y,k+1]+w[x,a[k]],f[x,a[k],k+1]+w[y,a[k]]);79 线性动态规划-----积木游戏F[i,a,b,k]=max(f[a+1,b,k],f[i+1,a+1,a+1,k],f[i,a+1,a+1,k]);80 树形动态规划(双次记录)-----NOI2003 逃学的小孩朴素的话枚举节点i和离其最远的两个节点j,k O(n^2)每个节点记录最大的两个值,并记录这最大值分别是从哪个相邻节点传过来的。

浅谈线段树优化DP

浅谈线段树优化DP

浅谈线段树优化DP
浅谈线段树优化DP
本篇随笔浅谈⼀下线段树优化DP。

⼀、关于DP优化的两种⽅式
DP算法是⼤家⽿熟能详的最优化算法之⼀。

有的时候,我们设计DP的时候,需要采取措施进⾏DP优化来适应题⽬对时间空间的要求。

⼀般来讲,DP的优化有两种⽅式:第⼀种是针对状态设计进⾏优化。

⽐如滚动数组优化⼀维。

⽐如0/1背包优化枚举,⽐如状压和倍增DP等等。

第⼆种是针对转移过程进⾏优化,⽐如⼀次转移是\(O(n)\)的,卡时间,就想办法通过⼀些办法把⼀次转移的时间复杂度降低。

⽐如,对于⼀些数列问题,可以通过递推公式进⾏通项公式的计算,进⽽做到\(O(n)\rightarrow O(1)\)的转移。

还⽐如说,⽤⼀些数据结构维护转移所需的⼀些信息,以达到优化转移的效果。

⼆、线段树优化DP的概念
在DP过程中架线段树对DP的转移进⾏优化,就被叫做线段树优化DP。

三、例题体会
多讲没⽤,上题。

⽐如这道:
这道题是很经典的线段树优化DP。

设计状态什么的都是次要的。

转移的时候,不加优化是⼀次\(O(n)\),优化后变成⼀次\(O(\log n)\),总复杂度变成:\(O(n\log n)\)。

通过这道题,我们总结⼀下线段树优化DP的⼀半步骤。

⼀、弄清楚线段树维护的是什么信息。

⼆、弄清楚线段树维护的信息在转移过程中是否有修改,怎么修改。

三、弄清楚线段树维护的信息在转移过程中是否随状态的更新⽽改变。

⼤约就是这样。

DP的内部结构扩展

DP的内部结构扩展
大投射 。 这时候动词已经联结了通常说的主语和宾语 , 但此时的 关系只是语义关系 , 动词这时只是给 主 语 和 宾 语 分 配 了 题 元 角 色 , 谁是主语谁是宾语还不知道 。 在文献 里 , 以 这 种 结 构 为 基 础 的 生 成 过 程 通 常 称 作 动 词 内 部 主 语 假 说 (VP-Internal Subject Hypothesis ), 见 Sportiche (1988 )。 生成继续进行 , 然后实现了下一 个最大投射 IP ( 后来也写成 TP 如 Chomsky 1995 :173 ), 即以时态 为核心的最大投射 。 值得注意的是 , 这个树节 (tree node ) 上下还 包含复杂的形态系统 , 也就是通常说的 AgrP , 如还可以分为 AgrsP 和 AgroP , 负责主语和宾语的形态 。 生成过程中 , 首先动词通过 移位到达这里实现时态 , 同时 , 主语和宾语也通过移位到达 AgrP 上相应的位置获得相应的形态一致 。 这 时 候 的 主 语 和 宾 语 实 现 了抽象格的核查 , 谁是主宾已经有了分晓 。 生 成 继 续 进 行 , 最 后 到达 CP , 完成整句的生成过程 。 如果句子是疑问句 , 相关的成分 还得移位到 CP 部分 , 如汉语里表示问句的词汇性语气词 [Q] 也在 这里出现 。 纵观整个生成过程 , 生成所经历的阶段大概可以分为 三 个 阶 段 ,vP 、TP 和 CP 。 这 就 是 Chomsky (1999 ) 所 说 的 语 段
域的划分可以充分表达了整个 DP 短语的生成过程 , 读者可以比 上 面 用 英 语 的 例 句 简 要 说 明 了 DP 引 入 能 产 域 分 析 法 的 意 义 。 派生分段法具有很强的解释力 。 为了进一步说明分段派生的 一 些 具 体 功 用 , 下 面 将 用 Ticio (2003 ) 对 西 班 牙 语 所 作 的 分 析 略

Codeforces1153D树形DP

Codeforces1153D树形DP

Codeforces1153D树形DP题意:有⼀个游戏,规则如下:每个点有⼀个标号,为max或min, max是指这个点的值是所有⼦节点中值最⼤的那⼀个,min同理。

问如何给这颗树的叶⼦节点赋值,可以让这棵树的根节点值最⼤。

思路:很明显的树形dp,设dp[x]是指以x为根的⼦树中可以获得的最⼤的值, sz[x]是指以x为根的⼦树中叶⼦节点的个数。

若x是max,那么dp[x] = max(sz[x] - sz[y] + dp[y]),对应的决策相当于把最⼤的⼏个值给dp[y] - sz[y]最⼤的那颗⼦树。

若x是min, ⾸先需要统计每颗⼦树的sz[y] - dp[y],这些都不可能被选上了,之后,还要统计有多少棵⼦树(假设有z棵), 其中z - 1个肯定选不上了,所以答案是sz[x] - Σ(sz[y] - dp[y]) - (z - 1)。

这两条对照这样例的图很容易就能发现了,然⽽昨晚思路跑偏了,这题都没做出来,含泪掉分。

代码:#include <bits/stdc++.h>using namespace std;const int maxn = 300010;vector<int> G[maxn];int sz[maxn], dp[maxn], a[maxn];void dfs(int x) {dp[x] = 1;if(G[x].size() == 0) {sz[x] = 1;return;}for (int i = 0; i < G[x].size(); i++) {int y = G[x][i];dfs(y);sz[x] += sz[y];}if(a[x] == 1) {for (int i = 0; i < G[x].size(); i++) {int y = G[x][i];dp[x] = max(dp[x], sz[x] - sz[y] + dp[y]);}} else {int tmp = 0;for (int i = 0; i < G[x].size(); i++) {int y = G[x][i];tmp += sz[y] - dp[y];}dp[x] = sz[x] - tmp - G[x].size() + 1;}}int main() {int n, x;scanf("%d", &n);for (int i = 1; i <= n; i++) {scanf("%d", &a[i]);}for (int i = 2; i <= n; i++) {scanf("%d", &x);G[x].push_back(i);}dfs(1);printf("%d\n", dp[1]);}。

poj3107(树的重心,树形dp)

poj3107(树的重心,树形dp)

poj3107(树的重⼼,树形dp)题⽬链接:https:///problem/POJ-3107题意:求树的可能的重⼼,升序输出。

思路:因为学树形dp之前学过点分治了,⽽点分治的前提是求树的重⼼,所以这题就简单⽔了⼀下。

⽤sz[u]记录⼦树u的⼤⼩,son[u]记录以u为根时,⼦结点中最⼤的结点数。

所以: son[u]=max(son[v],n-sz[u]),前⼀部分son[v]好理解,对于n-sz[u],即结点u的⽗结点那⼀块的⼤⼩。

AC code:#include<cstdio>#include<algorithm>using namespace std;const int maxn=50005;int n,cnt,head[maxn],sz[maxn],son[maxn];struct node1{int v,nex;}edge[maxn<<1];struct node2{int val,id;}ans[maxn];void adde(int u,int v){edge[++cnt].v=v;edge[cnt].nex=head[u];head[u]=cnt;}bool cmp(node2 a,node2 b){if(a.val==b.val) return a.id<b.id;return a.val<b.val;}void getroot(int u,int fa){sz[u]=1,son[u]=0;for(int i=head[u];i;i=edge[i].nex){int v=edge[i].v;if(v==fa) continue;getroot(v,u);sz[u]+=sz[v];son[u]=max(son[u],sz[v]);}son[u]=max(son[u],n-sz[u]);ans[u].val=son[u],ans[u].id=u;}int main(){scanf("%d",&n);for(int i=1;i<n;++i){int u,v;scanf("%d%d",&u,&v);adde(u,v);adde(v,u);}getroot(1,0);sort(ans+1,ans+n+1,cmp);printf("%d",ans[1].id);for(int i=2;i<=n&&ans[i].val==ans[1].val;++i)printf(" %d",ans[i].id);printf("\n");return0;}。

noi知识点

noi知识点

noi知识点加*号是选学,加粗为重点,重要值排序不分先后基础贪⼼、枚举、分治、⼆分、倍增、*构造、⾼精、模拟图论图最短路(dijkstra、spfa、floyd),差分约束最⼩⽣成树(kruskal、prim)并查集(扩展域)拓扑排序⼆分图染⾊,*⼆分图匹配tarjan找scc、桥、割点,缩点*分数规划树树上倍增(LCA)树的直径、树的重⼼dfs序*树链剖分数论gcd、lcm埃⽒筛法exgcd,求解同余⽅程、逆元快速幂*组合数学矩阵链表、队列(单调队列)、栈(单调栈)堆、st表、hash表线段树、树状数组字典树*分块动态规划背包DP、树形DP、记忆化搜索、递推区间DP、序列DP*DP优化(不涉及斜率优化、四边形不等式等等)搜索暴搜(dfs、bfs)搜索的剪枝启发式搜索(A*)迭代加深搜索、* IDA**随机化搜索其他算法STL的基本使⽤⽅法脑洞的正确使⽤⽅法*KMP*状态压缩冲省选的,先把整理的NOIP知识点学扎实,注意⼀定要学扎实加粗是重点,星号是选学学⽆⽌境,欢迎⼤家继续补充~图论⽹络流(dinic,SAP,ISAP选⼀个,费⽤流写EK就⾏。

*zkw费⽤流),⼆分图点分治,边分治,*动态点分治树链剖分,动态树,树分块虚树,*prufer编码*仙⼈掌算法带权并查集Splay(作为平衡树和维护区间),Treap,替罪⽺树线段树(权值线段树),树状数组,*线段树合并分块,块状链表,*双向链表凸包树套树主席树,可持久化trie,*其它可持久化数据结构莫队算法,*树上莫队,CDQ分治,整体⼆分⼆维线段树,*KDtree*舞蹈链,*⼆进制分组,*左偏树,*超哥线段树,*后缀平衡树,*fhqTreap字符串相关及数据结构hash(⾃然溢出,双hash)kmp,AC⾃动机,trie后缀数组manacher,最⼩表⽰法*后缀⾃动机,*回⽂⾃动机,*后缀树数学线性筛,积性函数,容斥原理,莫⽐乌斯反演exgcd,费马⼩定理,Lucas定理,⾼中排列组合⾼斯消元,概率与期望相关中国剩余定理,BSGS,欧拉定理矩阵乘法单纯形法解线性规划FFT线性代数(⾏列式)*Simpson积分,⾼中求导与积分*群论*⽣成函数,多项式类算法博弈论相关,*密码学,阶,原根计算⼏何向量的点积/叉积,计算⼏何基础*⼆维计算⼏何相关,*三维计算⼏何相关*半平⾯交,*旋转卡壳,*三⾓剖分搜索A*,记忆化搜索,迭代深搜,双向⼴搜模拟退⽕,爬⼭算法,*随机增量法动态规划基础DP,树形DP,数位DP,状压DP,期望DP,基环树DP,*插头DP斜率优化,矩乘优化,单调队列优化,倍增优化,*四边形不等式优化trie图DP,*仙⼈掌DP其他算法构造,乱搞,随机化,三分法,打表,启发式合并Huffman树,2-sat,*朱刘算法。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
树形动态规划
广东中山纪念中学 宋新波
例1最大利润
• 【题目描述】 • 政府邀请了你在火车站开饭店,但不允许同时在两个相连 接的火车站开。任意两个火车站有且只有一条路径,每个 火车站最多有50个和它相连接的火车站。 • 告诉你每个火车站的利润,问你可以获得的最大利润为多 少。 • 例如下图是火车站网络:
例2电子眼
• Input • 输入文件第1行包括一个数字N(1<=N<=100000),表示路 口数。接下来N行,第i+1行的第一个数字ki表示有ki条马 路与路口i相连,后面紧跟着ki个数字,表示与路口i直接 相连的路口。 • Output • 输出最少需要安装电子眼的数量。 • Sample Input • 3 • 223 • 213 • 212 • Sample Output • 2 • Source • GDKOI2006第2试第4题
分析
• 题目给出的模型正好是一棵树加上一条边, 所以一定有且仅有一个环 • 去掉环上任意一条边得到树 • DFS找到环上一条边,设连接x和y • 什么情况才能去掉呢? • X一定要选或者y一定要选就可以了 • 从而得到树形DP模型
分析
• f[x]表示在x处安装电子眼的情况下监控以x为根的 子树中所有边所需安装的最少电子眼数 • G[x]表示在x处不安装电子眼的情况下监控以x为根 的子树中所有边所需安装的最少电子眼数 • f[x]:= min(f[y],g[y])+1,其中y是x的儿子 • g[x]:= f[y],其中y是x的儿子 • 以x和y为根分别做一次树形DP • 答案就是min(f[x],f[y]),时间复杂度为O(N)
例3Debug
例3Debug
讨论例3
例4鱼肉炸弹例4鱼肉炸弹来自讨论例4i 1
max(F (Yi), G (Yi)) • G(X)= i 1 • 实现时用DFS去实现,每个点只需求一次,所以 时间复杂度为O(N)
K
例2电子眼
• 沈阳市是一个环境优美、气候宜人的城市。因为 城市的交通并不繁忙,市内的道路网很稀疏。准 确地说,沈阳市有N条马路和N个路口,每条马路 连接两个路口,每两个路口之间最多只有一条马 路。作为一条交通网络,显然每两个路口之间都 是可达的。为了更好地管理沈阳市的交通,市长 决定在一些路口加装电子眼,用来随时监视路面 情况。这些装在路口的电子眼能够监视所有连接 到这个路口的马路。现在市长想知道最少需要在 多少个路口安装电子眼才能监视所有的马路。市 长已经把所有的路口都编上了1~N的号码。 给你沈阳市的地图,你能帮忙吗?
• 最佳投资方案是在1,2,5,6这4个火车站开饭店可以获 得利润为90
• 【输入格式】 • 第一行输入整数N(<=100000),表示有N个火车站,分别用1, 2。。。,N来编号。接下来N行,每行一个整数表示每个站点的利润, 接下来N-1行描述火车站网络,每行两个整数,表示相连接的两个站 点。 • 【输出格式】 • 输出一个整数表示可以获得的最大利润。 • 【样例输入】 • 6 10 • 20 • 25 • 40 • 30 • 30 • 45 • 13 • 34 • 23 • 64 • 【样例输出】 • 90
分析
• 因为N个点,N-1条边,任意两个火车站有且只有 一条路径,所以是一棵树 • 我们用F[X]表示在以X为根的树中开饭店,X一定 要开,所能获得的最大利润,G[X] 表示在以X为 根的树中开饭店,X一定不开,所能获得的最大 利润,我们知道X开,则它的儿子们Y1,…Yk一定 不能开,X不开,它的儿子们可开可不开,于是 得到以下状态转移方程: K • F[X]= G (Yi) (Yi是X的儿子)
相关文档
最新文档