【序列dp】最长上升子序列(二)

news2024/11/24 5:43:44

文章目录

    • 最长上升子序列-序列dp
      • 1016 最大上升子序列和
      • 1010. 拦截导弹
      • 187. 导弹防御系统
      • 272.最长公共上升子序列
        • n^3 TLE
        • 优化

最长上升子序列-序列dp

  • 什么是序列相关的 DP ?
  • 序列相关 DP,顾名思义,就是将动态规划算法用于数组或者字符串上,进行相关具体问题的求解
  • 何时可以使用序列相关的 DP?
  • 当题目求解以下内容时,可以考虑使用序列相关的 DP
  • 给定两个字符串,求最长/大的某种值
  • 给定数组,求最长/大的某种值

此外,在使用序列相关的 DP 的时候,我们还需要注意到,这是一类的动态规划,所以需要满足动态规划的两种重要条件
最长上升子序列问题是一个经典的动态规划问题,目标是在给定序列中找到一个最长的升序子序列。

1016 最大上升子序列和

在这里插入图片描述

在这里插入图片描述

package acwing_plus.动规.最长上升子序列;

import java.util.Scanner;

/**
 * @author ty
 * @create 2023-03-31 10:00
 */
public class 最长上升子序列和 {
    static int N = 1010;
    static int[] a = new int[N];
    static int[] f = new int[N];
    static int n;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        for (int i = 1;i <= n;i++) {
            a[i] = sc.nextInt();
        }
        for (int i = 1;i <= n;i++) {
            f[i] = a[i];
            for (int j = 1;j < i;j++) {
                if (a[i] > a[j]) {
                    f[i] = Math.max(f[i],f[j] + a[i]);
                }
            }
        }
        int res = 0;
        for (int i = 1;i <= n;i++) {
            res = Math.max(res,f[i]);
        }
        System.out.println(res);
    }
}

1010. 拦截导弹

在这里插入图片描述

第一问:最长下降子序列

第二问:多少个最长下降子序列能覆盖整个序列

在这里插入图片描述

package acwing_plus.动规.最长上升子序列;

import java.util.Scanner;

/**
 * @author ty
 * @create 2023-03-31 11:29
 */
public class 拦截导弹 {
    static int N =  1010;
    static int n;
    static int[] q = new int[N];
    static int[] f = new int[N];
    static int[] g = new int[N];
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String[] line = sc.nextLine().split(" ");
        n = line.length;
        for (int i = 0;i < n;i++) {
            q[i] = Integer.parseInt(line[i]);
        }
        //先求最长下降子序列
        int res = 0;
        for (int i = n-1;i >= 0;i--) {
            f[i] = 1;
            for (int j = n-1;j > i;j--) {
                //题目要求是不高于上一个炮弹,所以此处下降序列可以连续相等
                if (q[i] >= q[j]) {
                    f[i] = Math.max(f[i],f[j] + 1);
                }
            }
            res = Math.max(res,f[i]);
        }
        System.out.println(res);
        //g数组存现有的子序列
        //cnt表示当前子序列个数
        int cnt = 0;
        for (int i = 0;i < n;i++) {
            int k = 0;
            //找到第一个最长下降子序列最后一个值,大于等于q[i]的
            while (k < cnt && g[k] < q[i]) k++;
            g[k] = q[i];
            //没有序列,能存储当前元素
            if (k >= cnt) {
                cnt++;
            }
        }
        System.out.println(cnt);
    }
}

187. 导弹防御系统

在这里插入图片描述

比1010变化:拦截系统新增可以单调上升的选择

即最少可以用多少个上升子序列和下降子序列将整个序列覆盖掉

此时不能用贪心,因为最开始还要面临选择上升还是下降,这是没法做到的,只能使用暴搜

在这里插入图片描述

package acwing_plus.动规.最长上升子序列;

import java.util.Scanner;

/**
 * @author ty
 * @create 2023-03-31 12:45
 */
public class 导弹防御系统 {
    static int N = 55;
    static int[] q = new int[N];
    static int[] up = new int[N];
    static int[] down = new int[N];
    static int n;
    //记录全局最小值
    static int ans;

    /**
     * @param u 当前枚举到第几个数
     * @param su 当前上升子序列的个数
     * @param sd 当前下降子序列的个数
     */
    private static void dfs(int u, int su, int sd) {
        if (su + sd  >= ans) return;//超出最小的ans
        //找到方案
        if (u == n) {
            //更新最小方案数
            ans = su + sd;
            return;
        }
        //情况一,将当前数放到上升子序列中
        int k = 0;
        //上升子序列是找到第一个小于它的数
        while (k < su && up[k] >= q[u]) {
            k++;
        }
        int t = up[k];
        up[k] = q[u];
        //说明没有开辟新的上升子序列
        if (k < su) {
            dfs(u+1,su,sd);
        }else dfs(u+1,su+1,sd);//开辟了新的上升子序列
        //恢复现场
        up[k] = t;

        //情况二:将当前数放到下降子序列中
        k = 0;
        while (k < sd && down[k] <= q[u]) k++;
        t = down[k];
        down[k] = q[u];
        //说明没有开辟新的下降子序列
        if (k < sd) dfs(u+1,su,sd);
        else dfs(u+1,su,sd+1);
        down[k] = t;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while ((n = sc.nextInt()) != 0){
            ans = n;
            for (int i = 0;i < n;i++) {
                q[i] = sc.nextInt();
            }
            dfs(0,0,0);
            System.out.println(ans);
        };
    }
}

272.最长公共上升子序列

最长公共子序列在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

划分方式

n^3 TLE

package acwing_plus.动规.最长上升子序列;

import java.util.Scanner;

/**
 * @author ty
 * @create 2023-03-31 14:22
 */
public class 最长公共上升子序列 {
    static int N = 3010;
    static int n;
    static int[] a = new int[N];
    static int[] b = new int[N];
    static int[][] f = new int[N][N];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        for (int i = 1; i <= n; i++) a[i] = sc.nextInt();
        for (int i = 1; i <= n; i++) b[i] = sc.nextInt();
        /*
        f[i][j]表示所有第一个序列中前i个字母和第二个序列中前j个字母构成的
            且以b[j]结尾的公共上升子序列的最长长度
        f[i][j]来自于
        情况一:不包含a[i]=>f[i-1][j]
        情况二:包含a[i],前提a[i]==b[j]
                ->再按照倒数第二个数的位置进行划分
                ->倒数第二个数的位置可以取,空值(即只有b[j]一个元素),b[1],b[2]...b[j-1]
                ->需要满足对于上述位置k,b[j]>b[k]
                =>f[i,j] = max(f[i,j],f[i,k]+1)
        最终答案是max(f[n,i]),i = 1...n
         */
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                f[i][j] = f[i - 1][j];
                //第二种
                if (a[i] == b[j]) {
                    //空集
                    f[i][j] = Math.max(f[i][j], 1);
                    for (int k = 1; k < j; k++) {
                        if (b[j] > b[k]) {
                            f[i][j] = Math.max(f[i][k] + 1, f[i][j]);
                        }
                    }
                }
            }
        }
        int res = 0;
        for (int i = 1; i <= n; i++) {
            res = Math.max(res, f[n][i]);
        }
        System.out.println(res);
    }
}

优化

import java.util.Scanner;

/**
 * @author ty
 * @create 2023-03-31 14:22
 */
public class Main {
    static int N = 3010;
    static int n;
    static int[] a = new int[N];
    static int[] b = new int[N];
    static int[][] f = new int[N][N];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        for (int i = 1; i <= n; i++) a[i] = sc.nextInt();
        for (int i = 1; i <= n; i++) b[i] = sc.nextInt();
        /*
        f[i][j]表示所有第一个序列中前i个字母和第二个序列中前j个字母构成的
            且以b[j]结尾的公共上升子序列的最长长度
        f[i][j]来自于
        情况一:不包含a[i]=>f[i-1][j]
        情况二:包含a[i],前提a[i]==b[j]
                ->再按照倒数第二个数的位置进行划分
                ->倒数第二个数的位置可以取,空值(即只有b[j]一个元素),b[1],b[2]...b[j-1]
                ->需要满足对于上述位置k,b[j]>b[k]
                =>f[i,j] = max(f[i,j],f[i,k]+1)
        最终答案是max(f[n,i]),i = 1...n
         */
        for (int i = 1; i <= n; i++) {
            int maxv = 1;//表示a[i]==b[j],1到j-1在满足a[i]>b[k]条件下的最大值
            for (int j = 1; j <= n; j++) {
                f[i][j] = f[i - 1][j];
                //第二种
                if (a[i] == b[j]) {
                    f[i][j] = Math.max(f[i][j], maxv);
                }
                /*
                这里的理解是,因为本质上之前更新的时候是b[k] < b[j]
                转换为b[k]<a[i]是因为b[j]==a[j],即选择到a[i]
                但是此时更新时,a[i]是我们将要寻找的b[j],可以理解为在执行到
                a[i]==b[j]之前的更新,都是没有选用a[i]的情况下的
                 */
                if (b[j] < a[i]) maxv = Math.max(maxv, f[i-1][j] + 1);

            }
        }
        int res = 0;
        for (int i = 1; i <= n; i++) {
            res = Math.max(res, f[n][i]);
        }
        System.out.println(res);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/667435.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

前端项目工程化搭建

ESLint 在开发过程中&#xff0c;需要遵循一些规范&#xff0c;可以使用下面的工具来配置不同项目需要遵循的规范&#xff0c;来帮助我们检查错误、约束开发过程。 ESLint 配置 使用 Taro CLI 创建的项目&#xff0c;会自动生成 .eslintrc 文件。只需要在这个文件的 rules 配…

web渗透

首先这道题目与ctf还是有点关系的&#xff0c;首先看一下题目&#xff1a; 通过浏览器访问http://靶机服务器IP/1&#xff0c;对该页面进行渗透测试, 找到flag格式&#xff1a;flag&#xff5b;Xxxx123&#xff5d;&#xff0c;括号中的内容作为flag值并提交&#xff1b;&…

关于深度学习训练的工程技巧

前置基础 不同精度数据类型的动态范围 FP16的动态范围(6x10-8 ~ 65504) FP32的动态范围(1.4x10-45 ~ 1.7x1038) 可以看出Fp32的动态范围远大于fp16; 其中BF16的取值范围&#xff1a; BF16&#xff08;BFloat16&#xff09;的取值范围也是按照IEEE 754标准定义的&#xff0c;…

破解时间序列:移动平均法的综合指南

目录 前言一、时间序列介绍1-1、时间序列定义1-2、时间序列特性1-3、时间序列作用 二、统计学方法2-1、移动平均法介绍2-1-1、基本原理、计算过程2-1-2、移动平均法分类2-1-3、简单移动平均法2-1-4、加权移动平均法2-1-5、指数移动平均法&#xff08;Exponential Moving Averag…

C# 反射(Reflection)总结

目录 什么是反射&#xff1f; 为什么使用反射&#xff1f; 反射机制的优缺点 如何使用反射&#xff1f; 一&#xff0c;Type访问元数据 获取/修改类中公有成员&#xff08;属性PropertyI和字段Field等&#xff09; 调用类中的公有构造函数Constructor 调用类中的公有方…

【软件工程】软件工程期末考试复习题

填空题&#xff08;每空1分&#xff0c;共25分&#xff09; 软件生存周期一般可以划分为&#xff0c;问题定义、可行性研究、需求分析、设计、编码、测试和运行和维护。基于软件的功能划分&#xff0c;软件可以划分成___系统软件_、支撑软件、应用软件__三种。可行性研究&…

【UE 从零开始制作坦克】10-炮弹溅射伤害

目录 一、解决炮弹穿过坦克炮塔问题 二、炮弹溅射伤害 效果 一、解决炮弹穿过坦克炮塔问题 打开“PHYS_West_Tank_M1A1Abrams”这个物理资产 造成这种现象的原因是&#xff0c;炮弹只会与如下紫色区域产生碰撞事件 选中坦克炮塔的骨骼 添加盒体外形 缩放盒体外形使其包裹住…

数据库原理之数据库事物

文章目录 一、事物介绍1.1 事物的目的是保证数据的一致性1.2 事物的ACID A、I、D是为了实现 C1.3 什么是本地事物(Local Transactions) 二、数据库系统如何实现ACID2.1 影响深远的ARIES理论2.2 本地事物如何实现原子性和持久性 A、D2.2.1 实现原子性和持久性的Commit Logging方…

基于高精度三维机器视觉的汽车曲轴无序抓取系统应用

Part.1 行业背景 汽车产业的高速发展&#xff0c;对零部件自动化生产提出了更高要求。随着汽车销量的水涨船高&#xff0c;传统的手工生产模式已经难以满足大批量生产的需求&#xff0c;自动化生产是必然趋势。 曲轴是汽车发动机的关键组件之一&#xff0c;生产过程复杂&#…

【MySQL】如何速通MySQL(4)

&#x1f4cc;前言&#xff1a;本篇博客介绍如何速通MySQL的第四篇&#xff0c;主要介绍Mysql中主要的基础的入门&#xff0c;学习MySQL之前要先安装好MySQL&#xff0c;如果还没有安装的小伙伴可以看看博主前面的博客&#xff0c;里面有详细的安装教程。或者看一下下面这个链接…

Linux(centos )防火墙常见操作

1、查看防火墙当前状态 systemctl status firewalld 2、开启防火墙 systemctl start firewalld 3、关闭防火墙 systemctl stop firewalld.service 4、如果报错&#xff1a;-bash: firewall-cmd: command not found&#xff0c;可能是没有安装 firewall。安装命令&#xff1a…

处理错误 Xcode 编译找不到文件 libarclite_iphonesimulator.a

处理错误 Xcode 编译找不到文件 libarclite_iphonesimulator.a 视频 https://youtu.be/ZBMFs2PwkB4 错误描述 Error (Xcode): File not found: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphonesimulator.aEr…

双非硕士-美国联培-马普所博士后-985系主任的逆袭之路

本科和硕士都是双非学校&#xff0c;博士期间曾有美国联合培养经历&#xff0c;毕业后到德国马普所从事博士后研究。现任985高校特聘教授、博/硕士生导师&#xff0c;系主任。知识人网小编特刊介绍李志明博士的逆袭之路。 随着国内就业压力的增大&#xff0c;高校招聘教师也呈现…

element 设置 table中的按钮权限

子组件 <template><!-- 二次封装表格&#xff0c; 仅支持单选 :style"{ height: height }"--><div class"self_table"><el-table:data"tableData"style"width: 100%"v-loading"loading"stripeselecti…

[游戏开发]Unity随机网格中空位置_二叉树

[目录] 0. 前言1. 简单随机2. 可用位置内随机3. 二叉树权重随机&#xff08;1&#xff09;分区域随机&#xff08;2&#xff09;设置权重均衡概率&#xff08;3&#xff09;二叉树缓存权重&#xff08;4&#xff09;利用二叉树随机&#xff08;5&#xff09;优缺点 4. 测试对比…

简要介绍 | Backbone与Baseline的区别

注1&#xff1a;本文系“简要介绍”系列之一&#xff0c;仅从概念上对Backbone和Baseline进行非常简要的介绍&#xff0c;不适合用于深入和详细的了解。 Backbone与Baseline的区别&#xff1a;从神经网络到性能基准 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来…

大厂测试员是如何编写测试用例呢?

一、测试用例是软件测试的核心 软件测试的重要性是毋庸置疑的。但如何以最少的人力、资源投入&#xff0c;在最短的时间内完成测试&#xff0c;发现软件系统的缺陷&#xff0c;保证软件的优良品质&#xff0c;则是软件公司探索和追求的目标。每个软件产品或软件开发项目都需要…

【活动总结】0617COC深圳社区首场线下AI技术沙龙活动最强总结

文章目录 活动的发起活动的宣传活动的进行活动的收尾活动的总结活动的致谢更多展望友情链接 就在2023年6月17日&#xff0c;CSDN COC 深圳城市开发者社区&#xff0c;在深圳大学组织了一次以【智能未来 —— 人工智能与城乡规划的交叉对话】为主题的线下沙龙活动&#xff0c;活…

基于spring boot的JsonSerializer 业务内容国际化

说起国际化&#xff0c;真的是老生常谈了。后端有各种i18n的依赖组件&#xff0c;springboot本身也支持i18n的设置&#xff0c;前端vue也有i18n的设置&#xff0c;这些常规操作就不提了&#xff0c;大家可以去搜索其他博客&#xff0c;写的都很详细。 本篇博客主要写的是业务内…

5大技巧,实现视频号预约直播人数暴涨!

两个体量相当的视频号&#xff0c;为什么别人的直播间人数过万&#xff0c;而自己的直播间却寥寥无几&#xff1f;这其中有一个非常重要的原因&#xff0c;就是预约直播的工作没有做好。 通常情况下&#xff0c;视频号直播预约人数和最终场观呈现1:10的比例&#xff0c;换言之…