第 377 场周赛 解题报告 | 珂学家 | Floyd + 划分型DP


前言

image.png


整体评价

天崩局,压哨绝杀,感谢天,感谢地,T_T.

感觉被T2玩惨了,T3和T4很像,无非一个贪心,一个是划分型DP,但是都需要基于floyd预处理。


T1. 最小数字游戏

思路: 模拟

排序/最小堆,模拟即可

class Solution {
    public int[] numberGame(int[] nums) {
        Arrays.sort(nums);
        List<Integer> res = new ArrayList<>();
        for (int i = 0; i < nums.length; i += 2) {
            res.add(nums[i + 1]);
            res.add(nums[i]);
        }
        return res.stream().mapToInt(Integer::valueOf).toArray();
    }
}

T2. 移除栅栏得到的正方形田地的最大面积

思路:彼此独立 + 枚举hash

这类题,大概率往横纵坐标彼此独立的角度去思考。

可以计算求的横坐标/纵坐标的可能取值,求交集的最大值即可。

这题感觉卡常,set必须得hashset, treeset会tle

class Solution {
    Set<Integer> convert(int n, int[] arr) {
        Arrays.sort(arr);

        Set<Integer> res = new HashSet<Integer>();
        res.add(n - 1);
        for (int i = 0; i < arr.length; i++) {
            res.add(arr[i] - 1);
            for (int j = 0; j < i; j++) {
                res.add(arr[i] - arr[j]);
            }
            res.add(n - arr[i]);
        }
        return res;
    }

    public int maximizeSquareArea(int m, int n, int[] hFences, int[] vFences) {
        long mod = (long)1e9 + 7;
        Set<Integer> rows = convert(m, hFences);
        Set<Integer> cols = convert(n, vFences);

        // 逆序遍历
        List<Integer> lists = rows.stream().sorted().toList();
        for (int i = lists.size() - 1; i >= 0; i--) {
            int v = lists.get(i);
            if (cols.contains(v)) {
                return (int)((long)v * v % mod);
            }
        }

        return -1;
    }
}

T3. 转换字符串的最小成本 I

思路:贪心

但是需要Floyd预处理,因为

A 到 B 的最小代 , 可能不是 A − > B 最短,有可能 A − > C − > B 最短 A到B的最小代, 可能不是A->B最短,有可能A->C->B最短 AB的最小代,可能不是A>B最短,有可能A>C>B最短

可能还需要注意,存在重边

class Solution {
    public long minimumCost(String source, String target, char[] original, char[] changed, int[] cost) {

        int inf = Integer.MAX_VALUE / 10;
        int[][] path = new int[26][26];
        for (int i = 0; i < 26; i++) {
            Arrays.fill(path[i], inf);
            path[i][i] = 0;
        }

        for (int i = 0; i < original.length; i++) {
            int s = original[i] - 'a';
            int e = changed[i] - 'a';
            path[s][e] = Math.min(path[s][e], cost[i]);
        }

        for (int k = 0; k < 26; k++) {
            for (int i = 0; i < 26; i++) {
                for (int j = 0; j < 26; j++) {
                    if (path[i][j] > path[i][k] + path[k][j]) {
                        path[i][j] = path[i][k] + path[k][j];
                    }
                }
            }
        }

        long res = 0;
        char[] bs = source.toCharArray();
        char[] ts = target.toCharArray();
        for (int i = 0; i < bs.length; i++) {
            int p1 = bs[i] - 'a', p2 = ts[i] - 'a';
            if (path[p1][p2] == inf) {
                return -1;
            }
            res += path[p1][p2];
        }
        return res;

    }
}


T4. 转换字符串的最小成本 II

思路:floyd + 划分型DP

把字符串视为节点,floyd预处理得到节点之间的转化代价,以为边稀疏,所以可以稍微优化下。

这题的关键是,两个描述的条件

操作的字符串没有重叠,满足划分型 D P 操作的字符串没有重叠,满足划分型DP 操作的字符串没有重叠,满足划分型DP

令 opt[i] 为以i结尾的转换最小代价

用刷表法转移

  • o p t [ i + 1 ] = m i n ( o p t [ i + 1 ] , o p t [ i ] ) , s o u r c e [ i + 1 ] = = t a r g e t [ i + 1 ] opt[i + 1] = min(opt[i+1], opt[i]), source[i+1] == target[i+1] opt[i+1]=min(opt[i+1],opt[i]),source[i+1]==target[i+1]
  • o p t [ i + w ] = m i n ( o p t [ i + w ] , o p t [ i ] + c o s t [ s o u r c e [ i + 1 : i + w + 1 ] ] [ t a r g e t [ i + 1 : i + w + 1 ] ] ) opt[i + w] = min(opt[i+w], opt[i] + cost[source[i+1:i+w+1]][target[i+1:i+w+1]]) opt[i+w]=min(opt[i+w],opt[i]+cost[source[i+1:i+w+1]][target[i+1:i+w+1]])
class Solution {

    long inf = Long.MAX_VALUE / 10;
    Map<String, Integer> idMap = new HashMap<>();
    long[][] path;

    void init(String[] original, String[] changed, int[] cost) {
       // 离散化, str -> id
       TreeSet<String> ts = new TreeSet<>();
       for (String w: original) ts.add(w);
       for (String w: changed) ts.add(w);

       int ptr = 0;
       for (var k: ts) {
           idMap.put(k, ptr);
           ptr++;
       }

       path = new long[ptr][ptr];
       for (int i = 0; i < ptr; i++) {
           Arrays.fill(path[i], inf);
           path[i][i] = 0;
       }

       for (int i = 0; i < original.length; i++) {
           int t1 = idMap.get(original[i]);
           int t2 = idMap.get(changed[i]);
           path[t1][t2] = Math.min(path[t1][t2], cost[i]);
       }

       // floyd
       for (int k = 0; k < ptr; k++) {
           for (int i = 0; i < ptr; i++) {
               // 稀疏表,大剪枝
               if (path[i][k] == inf) continue;
               for (int j = 0; j < ptr; j++) {
                   if (path[i][j] > path[i][k] + path[k][j]) {
                       path[i][j] = path[i][k] + path[k][j];
                   }
               }
           }
       }
    }

    public long minimumCost(String source, String target, String[] original, String[] changed, int[] cost) {

        // 对长度去重, 减少枚举次数
        TreeSet<Integer> ts = new TreeSet<>();
        for (String s: original) ts.add(s.length());
        for (String s: changed) ts.add(s.length());
        List<Integer> lens = ts.stream().toList();

        
        init(original, changed, cost);

        int n = source.length();
        char[] str1 = source.toCharArray();
        char[] str2 = target.toCharArray();

        // dp核心逻辑
        long[] dp = new long[n + 1];
        Arrays.fill(dp, inf);
        dp[0] = 0;
        for (int i = 0; i < n; i++) {
            if (str1[i] == str2[i]) {
                dp[i + 1] = Math.min(dp[i + 1], dp[i]);
            }

            // 这部分有优化空间
            for (int j = 0; j < lens.size(); j++) {
                int w = lens.get(j);
                if (w > n - i) break;
                String s = new String(str1, i, w);
                String t = new String(str2, i, w);
                if (idMap.containsKey(s) && idMap.containsKey(t)) {
                    dp[i + t.length()] = Math.min(dp[i + t.length()], dp[i] + path[idMap.get(s)][idMap.get(t)]);
                }
            }
        }

        return dp[n] == inf ? -1 : dp[n];
    }
}

写在最后

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

接口测试 — 11.logging日志模块处理流程

1、概括理解 了解了四大组件的基本定义之后&#xff0c;我们通过图示的方式来理解下信息的传递过程&#xff1a; 也就是获取的日志信息&#xff0c;进入到Logger日志器中&#xff0c;传递给处理器确定要输出到哪里&#xff0c;然后进行过滤器筛选&#xff0c;通过后再按照定义…

【LeetCode】链表精选11题

目录 快慢指针&#xff1a; 1. 相交链表&#xff08;简单&#xff09; 2. 环形链表&#xff08;简单&#xff09; 3. 快乐数&#xff08;简单&#xff09; 4. 环形链表 II&#xff08;中等&#xff09; 5. 删除链表的倒数第 N 个节点&#xff08;中等&#xff09; 递归迭…

量化投资策略的评估标准及其计算公式

收益率指标&#xff1a;分为策略的总收益率和策略的年化收益率 策略的总收益率&#xff1a; 策略的总收益率是评价一个策略盈利能力的最基本的指标&#xff0c;其计算方法为&#xff1a; 公式中Vt表示策略最终的股票和现金的总价值&#xff0c;V0表示策略最初的股票和现金的总…

探秘JDK 13的黑科技:新特性一览

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 探秘JDK 13的黑科技&#xff1a;新特性一览 前言switch表达式扩展Switch表达式的基本概念&#xff1a;使用Switch表达式的优势&#xff1a;示例代码&#xff1a;注意事项和最佳实践&#xff1a; Text …

Spring Cloud + Vue前后端分离-第7章 核心业务功能开发

Spring Cloud Vue前后端分离-第7章 核心业务功能开发 7-1 课程管理功能开发 课程管理页面美化 1.课程管理页面美化 demo-course.jpg 复制search.html中的部分代码 course.vue 看效果 测试一下新增修改删除效果 1.课程管理页面美化2 scoped:style下的样式只应用于当前组件…

LCT(link cut tree) 详细图解与应用

樱雪喵用时 3days 做了 ybtoj 的 3 道例题&#xff0c;真是太有效率了&#xff01;&#xff01;1 为了避免自己没学明白就瞎写东西误人子弟&#xff0c;这篇 Blog 拖到了现在。 图片基本沿用 OIwiki&#xff0c;原文跳步骤&#xff08;主要是 access 部分&#xff09;的就自己…

Spark编程实验三:Spark SQL编程

目录 一、目的与要求 二、实验内容 三、实验步骤 1、Spark SQL基本操作 2、编程实现将RDD转换为DataFrame 3、编程实现利用DataFrame读写MySQL的数据 四、结果分析与实验体会 一、目的与要求 1、通过实验掌握Spark SQL的基本编程方法&#xff1b; 2、熟悉RDD到DataFram…

如何利用flume进行日志采集

介绍 Apache Flume 是一个分布式、可靠、高可用的日志收集、聚合和传输系统。它常用于将大量日志数据从不同的源&#xff08;如Web服务器、应用程序、传感器等&#xff09;收集到中心化的存储或数据处理系统中。 基本概念 Agent&#xff08;代理&#xff09;&#xff1a; …

039、转置卷积

之——增大高宽 杂谈 通常来说&#xff0c;卷积不会增大输入的高宽&#xff0c;通常要么不变&#xff0c;要么减半&#xff1b;如果想要直接padding来增加高宽&#xff0c;在不断的卷积过程中&#xff0c;padding的0越来越多&#xff0c;最后要做像素级的判断时候&#xff0c;由…

分布式核心技术之分布式共识

文章目录 什么是分布式共识&#xff1f;分布式共识方法PoWPoSDPoS 三种分布式共识算法对比分析 选主过程就是一个分布式共识问题&#xff0c;因为每个节点在选出主节点之前都可以认为自己会成为主节点&#xff0c;也就是说集群节点“存异”&#xff1b;而通过选举的过程选出主节…

基于Java SSM框架实现医院挂号上班打卡系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现医院挂号上班打卡系统演示 摘要 在网络发展的时代&#xff0c;国家对人们的健康越来越重视&#xff0c;医院的医疗设备更加先进&#xff0c;医生的医术、服务水平也不断在提高&#xff0c;给用户带来了很大的选择余地&#xff0c;而且人们越来越追求更个…

【leetcode100-019】【矩阵】螺旋矩阵

【题干】 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 【思路】 不难注意到&#xff0c;每进行一次转向&#xff0c;都有一行/列被输出&#xff08;并失效&#xff09;&#xff1b;既然已经失效&#xff0c;那我…

MyBatis-Plus中默认方法对应的SQL到底长啥样?

我希望成为&#xff1a;自媒体圈中技术最好、实战经验最丰富的达人&#xff0c;技术圈中最会分享的架构师。加油&#xff01; 我的公众号&#xff1a;Hoeller 过段时间要给公司同事做Mybatis-Plus相关的培训&#xff0c;所以抓紧时间看看Mybatis-Plus的源码&#xff0c;顺便也分…

RT-Thread 内核对象管理框架

内核对象管理框架 RT-Thread采用内核对象管理系统来访问/管理所有内核对象&#xff0c;内核对象包含了内核中绝大部分设施&#xff0c;这些内核对象可以是静态分配的静态对象&#xff0c;也可以是从系统内存堆中分配的动态对象。 RT-Thread内核对象包括&#xff1a;线程&…

使用VisualStutio2022开发第一个C++程序

使用VisualStudio2022创建C项目 第一步&#xff1a;新建C的控制台应用 第二步&#xff1a;填写项目名称和代码存放位置&#xff0c;代码的存放目录不要有中文名 第三步:点击创建&#xff0c;VisualStudio会自动开始帮我们创建项目 第四步&#xff1a;项目创建好以后&…

2023,测试开发人的年终总结

根据TesterHome社区发帖整理。从该年终总结可以看出当前测试行业&#xff0c;哪怕是测试开发也是竞争很厉害。作为测试同仁&#xff0c;不但要掌握功能测试、接口测试、性能测试&#xff0c;掌握各种工具使用&#xff0c;还得懂开发&#xff0c;懂Java/Python&#xff0c;懂VUE…

洛谷——P3884 [JLOI2009] 二叉树问题(最近公共祖先,LCA)c++

文章目录 一、题目[JLOI2009] 二叉树问题题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示基本思路&#xff1a; 一、题目 [JLOI2009] 二叉树问题 题目描述 如下图所示的一棵二叉树的深度、宽度及结点间距离分别为&#xff1a; 深度&#xff1a; 4 4 4宽度&…

【AI提示词故事】《启示之星:寻找神殿的探险之旅》

故事叙述 在未来的某一天&#xff0c;人类发现了一个神秘的星球&#xff0c;被称为“启示之星”。传说在这颗星球上&#xff0c;有一座可以实现人类最大愿望的神殿。 启示之星 一支探险队被派往这颗星球&#xff0c;他们的目标是寻找神殿并实现自己的最大愿望。 在星球上&…

关于 curl 常用命令的使用整理【不定期更新】

目录 1. HTTP 请求2. 文件操作2.1 文件下载2.2 文件上传2.3 FTP 操作 3. 代理和网络设置4. 身份验证5. 调试和信息显示6. more and more curl 是一个用于在命令行下进行数据传输的工具&#xff0c;支持多种协议&#xff0c;包括 HTTP、HTTPS、FTP、FTPS、SCP、SFTP 等。它通常用…

结合ChatGPT和MINDSHOW自动生成PPT

总结/朱季谦 一、首先&#xff0c;通过chatGPT说明你的需求&#xff0c;学会提问是Ai时代最关键的一步。你需要提供一些关键信息&#xff0c;如果没有关键信息&#xff0c;就按照大纲方式让它设计&#xff0c;例如&#xff0c;我让它帮我写一份《2023年年中述职报告》的模版—…
最新文章