区间dp

求三个串的最长公共子序列
  • 题解
    在原先求两个串的最长公共子序列的二维dp上增加一维,变为三维dp。
    dp[i][j][k]表示A[1~i], B[1~j], C[1~k]的最长公共子序列的长度。
    状态转移方程:
    当A[i]=B[i]=C[i]时
    dp[i][j][k] = dp[i-1][j-1][k-1] + 1;
    其他时
    dp[i][j][k] = max(dp[i-1][j][k],dp[i][j-1][k],dp[i][j][k-1]);
    如果题目要求输出这个子序列的话,把数组改为字符串数组string,则状态转移方程如下
    当A[i]=B[i]=C[i]时
    dp[i][j][k] = dp[i-1][j-1][k-1] + A[i];
    其他时
    dp[i][j][k] = 上三个状态中长度最大的子序列
拦截导弹
  • 题意描述
    某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
    输出这套系统最多能拦截的导弹数和要拦截所有导弹最少要配备这种导弹拦截系统的套数。
  • 题解
    对于第一小问只需要求这个导弹序列的最长不上升子序列即可。
    对于第二问,我们去观察这个导弹序列的最长上升子序列,假设其长度为k,则需要的导弹拦截系统的套数>=k,因为每一发导弹都比前面的导弹高,不可能共用一套系统。
此时引入理论:完全覆盖一个序列的不上升子序列的个数等于这个序列的最长上升子序列的长度(严格的数学证明参考数学中偏序集的Dilworth定理)
  • 则需要的导弹拦截系统的套数就是k
  • 最长不上升子序列转移方程:dp[i]表示以a[i]为结尾的的最长不上升子序列的长度
    if(a[i]<=a[k]) dp[i] = max(dp[k]+1);(1<=k<=i-1)
    else dp[i] = 1;
    边界:dp[0] = 0;
    最后取最大值即可
NC16664 NOIP20041合唱队形
  • 题意描述
    N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。
    合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2...,K,他们的身高分别为T1,T2,...,TK,则他们的身高满足T,<...T+1>.….>Tk(1<=i<=K)。
    你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
解法一

枚举身高最高的同学的位置,以这个位置为基础,向左向右都是一个最长不上升子序列,从左往右求一个最长上升子序列记为F[i],从右往左求一个最长上升子序列记为G[i].
则答案为min(N-F[i]-G[i])(1<=i<=N).

解法二

dp[i][0/1]表示第i个同学必选,0表示位于上升序列中,1表示处于下降序列中
则状态转移方程为:
dp[i][0] = dp[k][0] + 1 (k<i且a[k]<a[i])
dp[i][1] = max(dp[k][1]+1,dp[k][0]+1)(k<i且a[k]>a[i])
最初给定的队列或结果可能是一个单纯的上升序列或下降序列

posted @ 2022-12-06 22:23  重生之我是菜鸟  阅读(25)  评论(0)    收藏  举报