DP刷题记录

dp刷题记录

codeforces 706C

题意:给出n个字符串,可以对每个字符串进行翻转操作,
每个操作对应一个消耗c[i],问经过操作后是否能满足字符串str[i]>=str[[i-1],能输出最小花费,不能输出-1

dp [i] [0]表示前i个字符串已经排好,最后一个字符串没翻转,dp[i] [1]表示前i个字符串已经排好,最后一个字符串翻转

边界:
d p [ 1 ] [ 0 ] = 0 ; d p [ 1 ] [ 1 ] = c [ 1 ] ; dp[1][0]=0; dp[1][1]=c[1];
方程:
= { d p [ i ] [ 0 ] = m i n ( d p [ i ] [ 0 ] , d p [ i 1 ] [ 0 ] ) , s t r [ i ] > = s t r [ i 1 ] d p [ i ] [ 0 ] = m i n ( d p [ i ] [ 0 ] , d p [ i 1 ] [ 1 ] ) , s t r [ i ] > = r e s t r [ i 1 ] d p [ i ] [ 1 ] = m i n ( d p [ i ] [ 1 ] , d p [ i 1 ] [ 0 ] + c [ i ] ) , r e s t r [ i ] > = s t r [ i 1 ] d p [ i ] [ 1 ] = m i n ( d p [ i ] [ 1 ] , d p [ i 1 ] [ 1 ] + c [ i ] ) , r e s t r [ i ] > = r e s t r [ i 1 ] 方程= \begin{cases} dp[i][0]=min(dp[i][0],dp[i-1][0]),\quad str[i] >= str[i - 1]\\ dp[i][0]=min(dp[i][0],dp[i-1][1]),\quad str[i] >= restr[i-1]\\ dp[i][1]=min(dp[i][1],dp[i-1][0]+c[i]),\quad restr[i]>=str[i-1]\\ dp[i][1]=min(dp[i][1],dp[i-1][1]+c[i]),\quad restr[i]>=restr[i-1]\\ \end{cases} \\
结果:
m i n ( d p [ n ] [ 0 ] , d p [ n ] [ 1 ] ) min(dp[n][0], dp[n][1])

codeforces 940E

题意:给你一个长度为n的序列和一个数c,你可以将序列划分成很多段,若其子序列的长度为k,那么就删除其中[k/c](向下取整)小的值,问你这些子序列最小的和是多少

dp[i]表示前i个数可以删掉的最大和
d p [ i ] = m a x ( d p [ i 1 ] , d p [ i c ] + m i n ( a [ k ] ) ) i c < k < = i dp[i]=max(dp[i-1],dp[i-c]+min(a[k]))\quad i-c<k<=i
单调队列优化,将O(n^2)优化为O(nlogn)

其中单调队列处理的是前c个数字中的最小的数

目标:
s u m d p [ n ] sum-dp[n]

BZOJ3997

题意:给我一个网格图,每次只能往下走或者往右走,经过每个格子是只能拿走一块财宝,问走多少次可以将财宝减完

Dilworth定理:DAG的最小链覆盖=最大点独立集
最小链覆盖指选出最少的链(可以重复)使得每个点都在至少一条链中
最大点独立集指最大的集合使集合中任意两点不可达

需要补充图论知识

将每一个财宝抽象成一个点,这就变成了一个有向无环图的最小路径覆盖

对于这类问题,我们知道最长反链=最小路径覆盖,所以求出这张图的最长反链就可以了。

对于一个点,它的左上角是可以到达的,但是右上角不能,所以用f[i][j] 表示以i,j为左下角的矩形的最长反链,则
f [ i ] [ j ] = m a x ( f [ i ] [ j + 1 ] , f [ i 1 ] [ j ] , f [ i 1 ] [ j + 1 ] + a [ i ] [ j ] ) . f[i][j]=max(f[i][j+1],f[i-1][j],f[i-1][j+1]+a[i][j]).

POJ2279

题意:有n个学生合影,站成左端对齐的k排,每排有ai个人,第一排站最后面,第k排站最前面,学生的身高互不相同,把他们的身高依次标记为1到n,要求合影时每一排从左到右身高递减、每一列从后到前身高也递减,问一共有多少种合影方案

杨氏矩阵又叫杨氏图表,它是这样一个矩阵,满足条件:

(1)如果格子(i,j)没有元素,则它右边和上边的相邻格子也一定没有元素。

(2)如果格子(i,j)有元素a[i][j],则它右边和上边的相邻格子要么没有元素,要么有元素且比a[i][j]大。

1 ~ n所组成杨氏矩阵的个数可以通过下面的递推式得到

F ( 1 ) = 1 , F ( 2 ) = 2 F ( n ) = F ( n 1 ) + ( n 2 ) F ( n 2 ) , ( n > 2 ) n 1 r e s = n ! / ( h o c k [ 1 ] h o c k [ 2 ] . . . . . h o c k [ n ] ) ; F(1)=1,F(2)=2 F(n)=F(n-1)+(n-2)*F(n-2),(n>2)\\ 对于给定形状,不同的杨氏矩阵的个数为:n!除以每个格子的钩子长度加1的积。 \\其中钩子长度定义为该格子 右边的格子数和它上边的格子数之和。\\ 钩子公式:res=n! / (hock[1]*hock[2]*.....hock[n]);

d p [ i ] [ j ] [ k ] [ p ] [ q ] i j k p q d p [ 0 ] [ 0 ] [ 0 ] [ 0 ] [ 0 ] = 1 = { d p [ i + 1 ] [ j ] [ k ] [ p ] [ q ] + = d p [ i ] [ j ] [ k ] [ p ] [ q ] ; i + 1 < = a [ 1 ] d p [ i ] [ j + 1 ] [ k ] [ p ] [ q ] + = d p [ i ] [ j ] [ k ] [ p ] [ q ] ; j + 1 < = a [ 2 ] j < i d p [ i ] [ j ] [ k + 1 ] [ p ] [ q ] + = d p [ i ] [ j ] [ k ] [ p ] [ q ] ; k + 1 < = a [ 3 ] k < j k < i d p [ i ] [ j ] [ k ] [ p + 1 ] [ q ] + = d p [ i ] [ j ] [ k ] [ p ] [ q ] ; p + 1 < = a [ 4 ] p < i p < j p < k d p [ i ] [ j ] [ k ] [ p ] [ q + 1 ] + = d p [ i ] [ j ] [ k ] [ p ] [ q ] ; q + 1 < = a [ 5 ] q < i q < j q < k q < p dp[i][j][k][p][q]表示各排从左端起分别站了i,j,k,p,q个人时合影的方案数量\\ 边界:dp[0][0][0][0][0]=1\\ 转移: 方程=\begin{cases} dp[i + 1][j][k][p][q] += dp[i][j][k][p][q];\quad i + 1 <= a[1]\\\\ dp[i][j + 1][k][p][q] += dp[i][j][k][p][q];\quad j + 1 <= a[2] && j < i\\\\ dp[i][j][k + 1][p][q] += dp[i][j][k][p][q];\quad k + 1 <= a[3] && k < j && k < i\\\\ dp[i][j][k][p + 1][q] += dp[i][j][k][p][q];\quad p + 1 <= a[4] && p < i && p < j && p < k\\\\ dp[i][j][k][p][q + 1] += dp[i][j][k][p][q];\quad q + 1 <= a[5] && q < i && q < j && q < k && q < p\\\\ \end{cases}

GYM102082D

SCNS(最短非公共子序列模板题)

最短非公共子序列:给你两个序列,求出不属于这两个序列的最短的子序列

解法:求出每个序列的每个位置后的第一个0,1的位置
d p [ i ] [ j ] [ 0 / 1 ] x y 0 / 1 dp[i][j][0/1]表示,在第一个序列的x位置和在第二个序列的y位置后,填上0/1是否满足非公共子序列
待补!!!!

codeforces132C

给一个序列,有TF,F代表机器人向前走一步,
T代表机器人转身,再给你一个N问改变N个字母后机器人最多可以走多远,
每个字母可以改变多次
d p [ i ] [ j ] [ k ] [ 2 ] i j k 0 / 1 d p [ 0 ] [ 0 ] [ l e n ] [ 1 ] = 1 ; = { d p [ i ] [ j ] [ k ] [ ! d ] = 1 ; s [ i ] = = T d p [ i ] [ j ] [ k + 1 ] [ d ] = 1 ; s [ i ] = = F , d = = 1 d p [ i ] [ j ] [ k 1 ] [ d ] = 1 ; s [ i ] = = F , d = = 0 d p [ i ] [ j + 1 ] [ k ] [ ! d ] = 1 ; j < n , s [ i ] = F d p [ i ] [ j + 1 ] [ k + 1 ] [ d ] = 1 ; j < n , s [ i ] = T , d = = 1 d p [ i ] [ j + 1 ] [ k 1 ] [ d ] = 1 ; j < n , s [ i ] = T , d = = 0 dp[i][j][k][2]表示前i个字母,改变了j次,当前停留在k位置,方向为0/1时的状态是否存在\\ 边界:dp[0][0][len][1]=1;\\ \\ 方程=\begin{cases} dp[i][j][k][!d]=1;\quad s[i]=='T'\\ dp[i][j][k+1][d]=1;\quad s[i]=='F',d==1\\ dp[i][j][k-1][d]=1;\quad s[i]=='F',d==0\\ dp[i][j+1][k][!d]=1;\quad j<n,s[i]='F'\\ dp[i][j+1][k+1][d]=1;\quad j<n,s[i]='T',d==1\\ dp[i][j+1][k-1][d]=1;\quad j<n,s[i]='T',d==0\\ \end{cases}

猜你喜欢

转载自blog.csdn.net/qq_41194925/article/details/88831539
今日推荐