随笔分类 - CH(AcWing)
摘要:这是一道树形dp的基本模型——树的最大独立集问题。 这种基本模型的解法是这样的:定义f[i][1/0]表示在以i为根的子树中,i选/不选的最小代价是多少,那么答案是min(f[0][1],f[0][0])。 考虑状态转移,对于i的每一个儿子j,若i选择,那么j可选可不选,如果i不选,那么j一定选。
阅读全文
摘要:一道多重背包的简化版问题,把多重背包的最优性问题简化为可行性问题,计算时只需将取最优值的一步改为或运算即可。 本题有解的条件:所有物品价值的一半能被表示出来。 本人使用了最简单的二进制优化即可通过本题。 1 #include <iostream> 2 #include <cstdio> 3 #inc
阅读全文
摘要:一道别样的区间dp,重点在于对字符串的处理。 读完题,我们很自然的想到区间dp,定义f[i][j]表示从折叠i~j的部分的最小长度,那么答案为f[1][n]。 区间dp的转移一般而言都是一样的,在区间中枚举一个位置,使这一个大区间分成两个小区间。因此状态转移方程我们不在赘述。 我们重点探讨一下对于字
阅读全文
摘要:一道线型dp的题目 每一种卡片有一定的数量限制,也就是说在计算到某一个状态时应当知道每一个卡片能不能用,所以我们定义状态f[i][j][k][l]表示第一种卡片用i张,第二张卡片用j张……所得到的最大值。 对于每一个状态,考虑他是怎样转移的。若当前状态为f[i][j][k][l],那么当前的状态可以
阅读全文
摘要:有关树形dp+二次扫描与换根法 首先我们读入数据,用邻接表存储,并记录每一个点相连的边的数量。 我们不妨先暂时假定节点1为树根,定义d[x]表示在以x为根的子树当中最大的流量,显然得出状态转移方程 d[x]=∑min(d[y],c(x,y)) 其中y∈son(x). 求出了d数组,我们考虑“二次扫描
阅读全文
摘要:一道非常棒的搜索题,做完之后感觉神清气爽…… 可以肯定的是,本题属于走地图一类的搜索题,适合用bfs求解,然而本题细节极多,有很多需要注意的地方。 我们定义状态三元组(x,y,z)表示当前移动到位置(x,y),且朝向z(我们不妨假定z=0意味着长方体立在地面上,z=1 意味着长方体横躺,x,y表示左
阅读全文
摘要:状压dp的一种经典模型,覆盖问题。 我们定义f[i][j]表示当第i行的状态为j时,前i行的方案数。显然答案为f[n][0]. 关于压缩状态,我们定义一个m位的二进制数,其中第i位为1的含义是,第i列是一个竖着的矩形的上半部分。第i位为0则表示其他情况。 因此,第i-1行的状态k能转移到第i行的状态
阅读全文
摘要:关于环形dp的处理,我采用的办法是,把整个问题分成两个问题。 首先我们简化一下问题,假设这个问题不是环形的,那么我们定义f[i][j][1]表示前i个小时休息了j小时,且第i小时正在休息,获得的体力最大值。定义f[i][j][0]表示前i个小时休息了j小时,且第i小时不在休息,获得的体力最大值。显然
阅读全文
摘要:树形dp可能是最优美的dp了…… 这是一道经典的树上背包问题,考虑两种做法。第一种是直接在树上做一遍背包问题,另一种是把这棵树转化成“左儿子右兄弟”的二叉树,再做一遍背包问题。 方法一:我们定义f[i][j]表示以i为根的子树,一共选j门课最大的分数,那么我们可以得到f[i][j]=max(f[i]
阅读全文
摘要:一道区间dp题,容易设计状态表示f[l][r]表示s[l~r]可能对应多少中金字塔方案数。 我们考虑在[l,r]中枚举一个k使得[l+1,k-1]作为l的一棵子树。那么s[l]应该等于s[k],状态转移方程为f[l][r]=∑f[l+1][k-1]*f[k][r]; 注意数据范围可能超过int,所以
阅读全文
摘要:一道区间dp题,不少细节。 一开始我想定义f[i][j]表示区间[i,j]通过某种合并之后的最大值,之后这道题就等同于“NOI1995石子合并”。 但是转念一想,这道题有加法和乘法两种运算,如果单看加法,以上思路正确。但是因为乘法的存在,两个较小的数(负数)相乘或许会大于两个最大数相乘,因此以上思路
阅读全文
摘要:区间动态规划的经典题,关于区间dp,状态定义是很显然的,定义f[i][j]表示把i~j这一区间合并花费的最小值,若i=j,则f[i][j]=0,若i≠j,则在i,j当中必定有一点k,使得i,j的区间先合并成i,k和k+1,j,然后合并成i,j.因此,对于每一对i,j,我们都枚举k,那么f[i][j]
阅读全文
摘要:关于多重背包的一道题。 首先看数据便知道朴素的多重背包无法通过,所以我们采用二进制拆分进行优化,(二进制优化点这里),这样就能顺利通过本题了。 这道题只是判断可行性,所以“价值”这一状态并没有什么用。 1 #include <iostream> 2 #include <cstdio> 3 #incl
阅读全文
摘要:也是一道线型动态规划的好题…… 读入每个人的贪婪度之后,对其按照从大到小的顺序排序,定义状态f[i][j]为前i个人(排序后)分j个饼干的答案,那么答案为f[n][m],考虑状态转移方程。 1、若给第i个人的饼干数大于1 ,那么我们将这i个人的饼干数都减1(总共减n),他们的怨气值是不会改变的,因而
阅读全文
摘要:显然,定义状态f[i][j][k][l]表示第一条路线走到(i,j),第二条走到(k,l)所取的数最大和。 状态转移方程即f[i][j][k][l]= max( max(f[i-1][j][k-1][l],f[i][j-1][k-1][l]), max(f[i-1][j][k][l-1],f[i][
阅读全文
摘要:线型动态规划的好题…… 分析题意,不难设计出状态:f[i][x][y][z]表示完成第i个任务后,三个人分别在x,y,z位置时的花费。但是这样的状态时间与空间都无法承受,不可行。 再次考虑:当完成第i个任务后,其中一人必定在p[i]上,因此状态可以减少一维:f[i][x][y]表示完成第i个任务后,
阅读全文
摘要:hash的入门题,通过hash我们可以在O(1)的时间里判断一个字符串的任意子串是否相等,恰好符合本题题意。 设计hash函数f[i]存储字符串s第1~i的子串的哈希值。显然存在f[i]=f[i-1]*131+(s[i]-'a'+1). 有了f数组,就可以求出任意子串的哈希值,因此我们就可以判断任意
阅读全文
摘要:最长公共上升子序列的模板题,仿照LCS和LIS的状态定义方式,我们定义f[i][j]表示a1~ai与b1~bj构成的以bj结尾的LCIS的长度,显然答案为max{f[n][i]}. 当ai≠bj时,f[i][j]=f[i-1][j]. 当ai=bj时,f[i][j]=max{f[i-1][k]+1}
阅读全文
摘要:这是一道基础数据结构的综合题,思考量较大,但是实现简单。 我们考虑建立三个队列,分别存储原始长度、切开后第一段的长度、第二段长度。显然,这三个队列是非严格单调下降的,对于每个时刻,将要切开的蚯蚓即为三个队列队头的最大值。另外,我们用一个变量delta表示整个集合的偏移值,即队列中的长度+delta=
阅读全文
摘要:一道简单的括号匹配问题,如果是左括号就入栈,如果是右括号且与栈顶匹配则答案加2,如果不匹配则答案清零,每次都更新一下最优答案即可。 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std
阅读全文