动规个人总结-DP-动态规划
留坑待填
给定01矩阵求最大国际象棋棋盘方法
对于01矩阵,求形如国际象棋的最大棋盘位置的方法(eg.LG1169)是:将横纵坐标和为偶数的点取反,即:
a[i][j] ^= (i ^ j) & 1
然后求最大同色正方形/矩形
求最大同色矩形
求出每个点向上最长延伸多长
给定序列 a[1...n],最少修改几个位置可以变成上升序列
令 a’[ i ] = a[ i ] - i,对 a’[ i ] 求最⻓不降⼦序列,可以得到最多有多少个位置保持不变;
如何改变,使前后数字变化量的绝对值的和最小?N<=35000,数据随机;
考虑dp:
单调队列维护凸包斜率优化DP
一个题能使用单调队列维护凸包,应该有以下几个条件:
1. 查询斜率单调。
2. 插入点的横坐标单调。
DP巧设状态
以中国象棋为例,询问NxM的棋盘,每行每列放置少于等于2个的棋子的方案数;
设
进阶
询问NxM的棋盘,每行每列必须放置2个棋子的方案数;
此题当然可以用上面的思路
再进阶
询问NxN的棋盘,每行每列必须放置2个棋子的方案数;
我们可以优化到
转移时这样讨论:
懒得写了
数位DP方法
为了免于数位DP最后的凑位步骤,在设计状态时可以加上一维,表示当前放置是否受限;
链接
树形DP注意环
RT,以P2515 [HAOI2010]软件安装为例,每个点均有一条出边,最后构成的图,可能是奇环树森林,由于依赖关系,一个环内的物品要么不选,要么都要选,所以需要Tarjan缩点;
Johnson 法则
可以概括为“双机器流水线问题”:有 n 个物品要由两台机器加工,每个物品都先在第一台机器上加工完成后再由第二台机器加工。第 i 个物品在两台机器上加工所需时间分别为
设两项任务分别为
基环树DP:骑士
在基环树森林中的没有上司的舞会;
处理的核心就在于处理环;考虑在环上的任意一点,它在最终答案中的情况只有两种:选/不选,每次强制规定一种状态,做一遍树形DP,取max;
注意图可能是森林;
划分数,求方案数
有n根木棍,第i根木棍的长度为Li,n根木棍依次连结了一起,总共有n-1个连接处。现在允许你最多砍断m个连接处,砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小,并且输出有多少种砍的方法使得总长度最大的一段长度最小。
一定不要把正解写挂了
第一问二分;第二问,注意到,朴素的dp,解的来源是后缀小于等于len的部分,前缀和优化即可;
求区间和的问题,最好直接转化为前缀和相减
预处理出最长后缀;
for(ri i = 1, c = 0; i <= n; ++i) {
sum[i] = sum[i - 1] + w[i];
while(sum[i] - sum[c] > len) ++c;
lef[i] = c;
s[i] = (s[i - 1] + (sum[i] <= len)) % md;
}
int ans = (sum[n] <= len);
for(ri j = 2; j <= m + 1; ++j) {
for(ri i = j; i <= n; ++i) {
f[i] = (s[i - 1] - s[lef[i] - 1] + md) % md;
}
(ans += f[n]) %= md;
s[0] = 0;
for(ri i = 1; i <= n; ++i) {
s[i] = s[i - 1] + f[i];
}
}
变形的背包
有n种物品,每种物品有两套cost和val,每个物品必须选一套,求各个总cost下的最大/最小总val;
如何处理必须选?以最小值为例:
滚动数组,每次把待更新的数组设为inf,转移时,枚举两种转态,都使用上一个数组转移;
为什么?首先,两个状态,不是一个依赖另一个的dp数组转移过来的,所以两个转态是独立的(不会都选);而初始dp数组为inf,要想转移,必须依靠上一个数组不为inf的位置,这就相当于每个物品,能选的话必须选;换句话说,取min不是和f[i-1]取(代表不选这个)而是和f[i]取;
区间DP
最好写循环,不写记忆化;
遇到特殊的情况:初值不方便设,答案不方便统计,怎么办?
刷表法:按照转移的顺序来;每一步都更新ans;
合并数列
有n个正整数,(2<=n<=262144),范围在1-40。可以选相邻的两个相同的数,然后合并成一个比原来的大1的数(例如两个7合并成一个8),目标是使得最大的数最大,请求最大值。
类似倍增的思想,非常有意思:
2.考虑i号牌碰(三张相同):
3.考虑i号拍杠(四张相同):
4.考虑i-2,i-1,i三张牌吃(三个连续数字):
最后结果为
如何满足“两人得分相同”的要求?
我们只要求相同,具体是多少不重要,所以我们直接记录两人得分之差即可;
刷表法会比填表法慢一些,也更可能RE???
拆分数列
给出一列数字,需要你添加任意多个逗号将其拆成若干个严格递增的数。如果有多组解,则输出使得最后一个数最小的同时,字典序最大的解(即先要满足最后一个数最小;如果有多组解,则使得第一个数尽量大;如果仍有多组解,则使得第二个数尽量大,依次类推……)。
首先要编写一个比较函数,忽略前导零;
设
在得到
设
输出方案时就从1开始不停的跳f;
注意 1234050 的最优方案是 12,34,050;
所以对于d[n]之前的前导零,要进行特判,
P3084 [USACO13OPEN]照片Photo
农夫约翰决定给站在一条线上的N(1 <= N <= 200,000)头奶牛制作一张全家福照片,N头奶牛编号1到N。
于是约翰拍摄了M(1 <= M <= 100,000)张照片,每张照片都覆盖了连续一段奶牛:第i张照片中包含了编号a_i 到 b_i的奶牛。但是这些照片不一定把每一只奶牛都拍了进去。
在拍完照片后,约翰发现了一个有趣的事情:每张照片中都有且仅有一只身上带有斑点的奶牛。约翰意识到他的牛群中有一些斑点奶牛,但他从来没有统计过它们的数量。 根据照片,请你帮约翰估算在他的牛群中最多可能有多少只斑点奶牛。如果无解,输出“-1”。
很神的DP;主要难点是不知道如何设置状态,因为要知道上一个放置的位置;
用f[i]f[i]表示到第i个位置为止且第i个位置必放,最多能放多少个
因为有两个限制条件:每个区间至少一个,每个区间至多一个
因为一个区间至多一个,所以所有包含这个点的区间都不能再放,要找到所有包含这个点的区间中最小的左端点,令r[i]=左端点-1(r[i]的初值均为i-1)
因为一个区间至少一个,所以不能有地方空着不放,找到整个区间在当前点之前的区间,取最大的左端点,令l[i]=左端点
每一次读入的时候,用x更新l[y+1]用x-1更新r[y]
然后正着扫一遍,用l[i-1]更新l[i](在i-1之前的左端点必定在i之前);然后倒着扫一遍,用r[i+1]更新r[i](注意覆盖n+1)
所以
把可行性DP转化为最优化DP,往往可以消掉⼀维
[APIO2015]巴厘岛的雕塑
给定⻓度为 N 的序列,和参数 A、B
• 把序列划分成 K(A <= K <= B)段,最⼩化每⼀段
的和的或
• Part1 : N <= 100
• Part2 : N <= 2000, A = 1
Part 1:
划分的段数有上下界,设
可行?什么是可行?
根据位运算的性质,我们往往都要按位考虑,每一位优先考虑填0,再考虑填1;
可行=这一位是0;
但是当我们确定了前几位的01后,对后面的分组是有限制的;
具体来说,之前已经确定填0的位,我们在后面分组的时候就不能填1;
也就是
if((((s[i] - s[k - 1]) >> w) & 1) == 0 && ((((s[i] - s[k - 1]) >> (w + 1)) << (w + 1)) | ans) == ans)
f[i][j] |= f[k - 1][j - 1];
这一段的和这一位是0,且之前ans是0的都是0;
对于Part 2:
我们只有了分组的上线:考虑如果没有分组的任何限制,我们一定是把每个数分成一组,而有了限制,我们就想尽可能多的分组;设
我们就优化掉一维了;
DP优化状态,可以尝试交换维度,或把目标量当作已知量作为一维
bzoj3090:
有 N 个农民, 他们住在 N 个不同的村子里. 这 N 个村子形成一棵树.
每个农民初始时获得 X 的钱.
每一次操作, 一个农民可以从它自己的钱中, 取出任意数量的钱, 交给某个相邻村子的农民.
对于每个农民给定一个值 v_i, 求最少需要多少次操作, 使得每个农民最终拿到的钱 >= 给定的值.
容易想到一种DP:
但是钱数很大,时空不允许???
交换状态,考虑到交换次数是N级别的;
如果
在实现转移方程时,要注意观察决策集合的范围随着状态的变化情况,对于“决策集合中的元素只增多不减少”的情景,可以维护一个变量记录当前决策集合的信息,避免重复扫描
有时可以通过额外的算法确定DP状态的顺序,有时可以在状态空间中运用等效的手法对状态进行缩放
以cookies为例:
圣诞老人共有M个饼干,准备全部分给N个孩子。每个孩子有一个贪婪度,第 i 个孩子的贪婪度为 g[i]。
如果有 a[i] 个孩子拿到的饼干数比第 i 个孩子多,那么第 i 个孩子会产生 g[i]*a[i]的怨气。
给定N、M和序列g,圣诞老人请你帮他安排一种分配方式,使得每个孩子至少分到一块饼干,并且所有孩子的怨气总和最小。
1≤N≤30, N≤M≤5000, 1<=gi<=10^7。
一个孩子的怒气大小与其他孩子获得的饼数有关,很难产生子结构;
思考可以发现,贪婪度大的孩子应该获得更多的饼干,因此把N个孩子按照贪婪度从大到小排序,他们分得的饼干数量将是递减的;
设
等价转换:
1.若第i个孩子获得的饼干数大于1,则等价于分配
2.若第i个孩子获得的饼干数量为1,枚举i前面有多少孩子也获得1块饼干;
数位DP
在设计状态时,最好不要设为:后面的位要满足...状态;而是设为,前面的位已经满足了...状态,后面的位全部满足状态的方案数;