随笔分类 - ACM / 动态规划 线性dp
摘要:原题链接 考察:线性dp 思路: 将$k$个连续的点当作$a$,一个点当作$b$.假设当前有$x$个点,那么我们要用$a,b$组成$x$ \(\quad \quad \quad f[x] = f[x-1]+f[x-k]\) ##Code #include <iostream> #include <c
阅读全文
摘要:原题链接 考察:线性dp 思路: 一开始完全没想到dp,看了题目的算法标签才做出来() $f[i][j]$记录当前位是$i$,符合要求的子序列上一位是$j$的最长长度. $dp$转移: 找到上一位与$a[i]$相等的位置$k% $k$存在 \(f[i][j] = f[j][k]+1\) $k$不存在
阅读全文
摘要:原题链接 考察:线性dp 思路: 想到了但三重循环以为会超时,实际是只有$j=1$时才有三重循环. ##Code #include <iostream> #include <cstring> using namespace std; const int N = 1010; int n,m,x,y,c
阅读全文
摘要:原题链接 考察:线性dp+二分 思路: 严格上升子序列长度,每个$a[i]-=i$,然后求非严格单调上升子序列长度. ##Code #include <iostream> #include <cstring> using namespace std; const int N = 100010; in
阅读全文
摘要:原题链接 考察:线性dp(状态机dp?) 错误思路: 对于每个数字按出现次数sz与值val的乘积排序,假设第一个值为x,$x*sz[x]>(x-1)*sz[x-1]\(但这并不表明\)(x-1)*sz[x-1]+(x+1)sz[x+1]会<xsz[x]$.所以贪心是不可取的. 正确思路: 选择没有规
阅读全文
摘要:原题链接 考察:线性dp or 枚举 大佬的思路: 0不能出现在1的右边,所以是单调非下降子序列,求最长即可. 本菜狗的思路: 枚举每一个1的位置,求保留前面所有0和后面所有1的长度,取最长即可. ##Code #include <iostream> #include <cstring> #incl
阅读全文
摘要:原题链接 考察:线性DP 错误思路: 求出最长公共子序列再dfs回溯枚举长度. 错误原因: 不一定只存在一个最长公共子序列.比如样例2. 正确思路: 是dp(...),定义 f[i][j] 为以1~i,1~j构成的最长公共子序列的最大S值,且A子串以i结尾,b子串由j结尾.这里其实类似最大连续子段和
阅读全文
摘要:原题链接 考察:线性dp 思路: 二分求最长上升子序列板子题,我们可以发现二分求得的最长上升队列中,保存的就是当前长度最小的数字,因此我们只需要每覆盖一个存储它们前面一个,最后递归输出. ##Code #include <iostream> #include <cstring> #include <
阅读全文
摘要:原题链接 考察:线性dp 思路: 其实递推方程超简单,只是我蠢. if(s[i]>s[j]) dp[i]+=dp[j] else if(s[i]==s[j]) dp[i]-=dp[j]; 如果s[i]==s[j],那么dp[i]从前面<s[i]获得的子序列都要减去,因为与s[j]构成了重复. ##C
阅读全文
摘要:原题链接 考察:线性dp 思路: 这道题就和POJ 1661差不多.f[i][0/1]表示到达第i条线段的0(左),1(右)的最小距离. f[i][0] = min(f[i-1][0]+i-1条线左端点到i条线左端点的最短距离,f[i-1][1]+i-1条线右端点到第i条线左端点的最小值) 同理右端
阅读全文
摘要:原题链接 考察:线性dp 此题不会,fw本f 思路: 求方案数且需要取模,基本上使用dp求解. 根据题目,dp状态一定要记录a取到哪一位,b匹配到哪一位,同时还有段数限制,所以还需要记录段数.所以设置f[i][j][k]为以a的前i位匹配了b前j位,已经用了k段. 此时还发现对于第i位,我们需要判断
阅读全文
摘要:原题链接 考察:线性dp 思路: 一开始的思路是定义结构体dp数组,但是会出现到达同一点剩余卡片种类不同的情况,只要卡片种类不同就会获得不同的分数,所以必须记录剩余卡片种类. 考虑到M很小,cnt(每种卡片)<=40.可以考虑开数组f[i][j][k][p][q] 表示到i点时剩余卡片为j,k,p,
阅读全文
摘要:原题链接 考察:线性dp+贪心 本蒟蒻真真菜到抠脚...二维MLE,滚动后TLE,绝望...已经菜到不会写普及组的题. 错误思路: 设f[i][j]为i秒时魔力为j的最大距离,总共三种决策: 一、 休息, f[i][j] = f[i-1][j] 二、 魔法,f[i]j] = f[i-1][j+10]
阅读全文
摘要:原题链接 考察:有限状态机dp+kmp 鬼才想得到的解法 思路: 在验证某串a是否为b的子串时,常常使用kmp算法.当子串匹配下标j = 子串长度时,说明串a是串b的子串.如果i取到串b的最后一位时,j还没有 = a长度,说明a不是b的子串. 在这道题,我们需要构造串b,使得a不是b的子串,也就是j
阅读全文
摘要:原题链接 考察:线性dp 思路: 很容易想到f[i][j]表示前i趟运了j头牛的最小时间(本蒟蒻虽然想到了但因为会T放弃了这个想法,所以会T的做法先想想看能不能优化啊啊啊) 所以f[i][j] = f[i-1][k]+sum[j-k]+2*m(这里会在最后一次多算一次m,最后答案减去即可).最后答案
阅读全文
摘要:原题链接 考察:dfs+dp 思路: 很像NOI1999的导弹拦截,但是这道题的决策需要决定是加入上升子序列还是下降子序列,然后判断加入到哪一个上升子序列. 多决策问题多用dp或搜索,这道题用dp需要记录的状态有:当前第几个数,当前上升子序列个数,当前下降子序列个数,但关键是当前最优解不一定能推到全
阅读全文
摘要:原题链接 考察:线性dp LIS的延伸题 思路: 当区间没有重叠部分的时候,就可以加上+f[j]. 注意:当有重叠部分的时候,不能f[i] = max(f[i],f[j]),如果数据eg:[1,10] [2,3] [4,19]3区间会把2区间加上,而2区间必须是原w . 1 #include <io
阅读全文
摘要:原题链接 考察:线性dp 这也能dp系列,完全没想到. 注意这道题是检查子矩阵,所以不用围绕主矩阵的对角线检查. 思路: 枚举子矩阵的左下角坐标,定义f[i][j]是以(i,j)为左下角坐标的最长对称边长.可以发现f[i][j]的最大边长最多为f[i-1][j+1]+1.三重循环枚举即可. 这题的原
阅读全文
摘要:原题链接 考察:线性dp 错误思路: f[x][y]代表坐标(x,y)的最少时间,状态转移方程推不出来,而且完全没有用到木板 正确思路: 上面的状态表示其实比较接近.dp问题要将大问题分解为若干个小问题.将起始点看作一块木板,f[i][0]表示从左边跳下去的最短时间,f[i][1]表示从右边跳下去的
阅读全文
摘要:原题链接 考察:线性dp 思路: 很容易看出状态转移方程,坑到本蒟蒻的是计算时间,总之请记下来.... 这里的f[n]是秒数. 1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 const int N = 2010
阅读全文