LC15. 三数之和

 题目来源于力扣题库,题目链接:LC15. 三数之和

Q:给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

示例2:

输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例3:

输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。

提示:

  • 3 <= nums.length <= 3000
  • -105 <= nums[i] <= 105

A:思路:题目给出的要求是从一个整数数组中不断找到三数之和为0的三元组,条件是这三个数所对应的索引均不相同,且结果集中不能存在重复的三元组。

  拿到该题,最容易想到的是用暴力解法,三个for循环开干。但是,通过对时间复杂度的一个分析,发现这样是行不通的,随后,曾经做过的两数之和的思路可能突然间给了自己一个思路,即用哈希表来做。事实上,利用哈希表是可以做出来的,但是过程有些过于复杂,尤其是对于去重问题,且时间复杂度也不低。

  最后,只能去求助于双指针,双指针的主要思路是先对数组进行排序,然后利用一层for循环去的固定一个数值nums[i](i∈[0, nums.length - 1]),随后构建两个指针left和right,初始化使得left = i + 1,right = nums.length - 1(left指向i的下一个数值,right指向nums的最后一个数值),在while(left < right)循环中,去使得left和right不断的靠近,即left++,right--。由于数组是经过排序的,所以是递增的,当遇到nums[i] + nums[left] + nums[right] > 0时,说明和太大了,那么我们就让right指针往前移动right--,使得和变小一点;同理如果遇到nums[i] + nums[left] + nums[right] < 0时,那么说明总和太小了,我们就让left指针往后移动left++,使得和变大一点。这样不断的去找到满足nums[i] + nums[left] + nums[right] == 0 的三个数值,且它们的下标是不重复的,但是还有一个问题就是,如何解决结果集中重复的三元组组合问题呢?

  这里便涉及到了关键的操作:去重,如何去重,举例来讲,例如有一数组: {-1, -1, -1, 2},我们可以发现,里面的一个组合{-1, -1, 2}是满足题意的,但是如果不进行去重操作,那么就会出现重复的三元组{-1, -1, 2}。解决该问题的一个关键思路是如果当前for循环中需要固定的数值num[i] == nums[i-1]时,就直接continue,跳过此轮for循环。为什么要这样?因为nums[i - 1]已经被我们用过了,且其后面对应的一些可以满足组合的数值也都用过了,均加入了结果集中了。那么如果现在我们还使用与nums[i-1]相同数值的nums[i],并且同样的往后找到满足的组合,那么必定会出现重复的三元组,简单来说就是又以同样的数值nums[i]去找了一遍满足题意的组合。

  故我们得知去重的第一个条件就是在for循环中,如果遇到i > 0 && nums[i] == nums[i - 1],则直接continue,开启下一轮for循环。但是现在似乎只完成了一次去重,还有二次去重,例如nums:{0, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1},我们可以很容易的找到满足题意的三元组{0,-1,1},但是此时会出现往后的{0,-1,1}还是满足的,显然这是不符合题意的,虽然它们三个下标不同,但是三元组是重复的。其实这个问题其实很好解决,当我们发现nums[left] == nums[left + 1] 时,就让left指针不断的往后移动,即left++,跳过那些重复的数值;同理当我们发现nums[right] == nums[right - 1]时,就让right指针不断的往前移动,即right--即可,至此,二次去重问题便解决了。

  最后要说的是,每当找到一组满足题意的三元组加入到结果集后,且二次去重完成后,还要进行一次left++和right--,使得left和right指针指向下一个需要判断的三元组。

  以下是Java代码,仅供参考:

 

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();

        int n = nums.length;

        Arrays.sort(nums); // 排序

        for(int i = 0; i < n; i++){
            if(nums[i] > 0) return res; // 排序后的第一个数值如果已经大于0,则直接返回res

            if(i > 0 && nums[i] == nums[i - 1]) continue; // 一次去重

            int left = i + 1; // 对于每一次的i,更新left
            int right = n - 1; // 对于每一次的i,更新right

            while(left < right){
                int sum = nums[i] + nums[left] + nums[right];

                if(sum < 0){ // 总和太小了,使left往后挪一挪
                    ++left;
                }else if(sum > 0){ // 总和太大了,使right往前挪一挪
                    --right;
                }else{
                    res.add(Arrays.asList(nums[i], nums[left], nums[right])); // 收集结果
                    while(left < right && nums[left] == nums[left + 1]) ++left; // 二次去重
                    while(left < right && nums[right] == nums[right - 1]) --right; // 二次去重

                    ++left; // 指向下一个待判断的数值
                    --right; // 指向下一个待判断的数值
                }
            }
        }
        return res;
    }
}

 

本文转载于网络 如有侵权请联系删除

相关文章

  • MYSQL-连续登陆的天数

    数据求连续登陆的天数CREATETABLE`t_login`( `id`bigint(20)NOTNULLAUTO_INCREMENT, `name`varchar(255)DEFAULTNULL, `login_date`dateDEFAULTNULL, PRIMARYKEY(`id`) )ENGINE=InnoDBAUTO_INCREMENT=11DEFAULTCHARSET=utf8; INSERTINTO`blog`.`t_login`(`id`,`name`,`login_date`)VALUES('1','丁D','2020-05-27'); INSERTINTO`blog`.`t_login`(`id`,`name`,`login_date`)VALUES('2','丁D','2020-05-26'); INSERTINTO`blog`.`t_login`(`id`,`name`,`login_date`)VALUES('3',&#x

  • Essential Phone Root教程

    EssentialPhoneRoot教程注意:此教程是仅针对essentialphone的root教程,不同手机root方法不同,只可借鉴,不可照搬机型介绍具体的介绍见链接,篇幅有点长就不写在这里了 详细评测为啥root机型选这款?开放性,这款是安卓之父退出的一款机型,开放性比国内厂商高很多;room完整性,官网上有从Android7.1.1~10所有的room链接,可以刷至任意版本,并且民间也有很多第三方的room;recovery完备,TWRP有专门对此机型开发的recovery,可以做很多其它的操作:比如刷入busybox、xposed等框架;配置及预算,部门预算有限,这款机型价格便宜,但配置是晓龙835的处理器4GB内存128G存储,在采购后今后3年内配置也是够的;Android版本选择由于Android10.0以后无法直接获取IMEI,在拿Android10中root的手机交给其它项目做开发的时候便遇到了这个问题,无法做到我们的工具获取IMEI的方式和app一致,所以选择了Android10.0的前一个版本:Android9root详细教程方式1:参见知乎专栏方式2:知乎专栏

  • jmetal随机数

    jmetal随机数util.PseudoRandomimportmomfo.util.JMException; importmomfo.util.PseudoRandom; importjava.io.IOException; publicclassTEST{ publicstaticvoidmain(Stringargs[])throwsIOException,JMException,ClassNotFoundException{ doublea; intb; System.out.println("a"); for(inti=0;i<10;i++){ a=PseudoRandom.randDouble();//[0,1)之间Double随机数 System.out.print(a+""); } System.out.println(); System.out.println("a1"); for(inti=0;i<10;i++){ a=PseudoRandom.randDouble(4,6);//[4,6)

  • IM即时通信探索(一)-- IM的即时通信初见

    大家好,我是黑眼圈云豆。这个系列的文章主要是针对IM功能进行探索,逐步实现一个相对功能较为完整的IM项目。今天先给大家介绍一下IM这个产品。架构介绍论聊天软件的实例,腾讯就不用多说了,经历了这么多年的经验和技术整合出来的IMSDK目前已经能够完整应用在Android、iOS、Windows、Web等平台上了。目前sdk已经整合了单聊和群聊服务。单聊单聊即1V1聊天,提供包括文字、表情、地理位置、图片、语音、短视频及自定义消息的能力,可实现红包、对话机器人、消息回执、消息撤回等特殊功能,除此之外还提供离线消息、漫游消息等服务。群聊多人聊天服务,根据群组加群方式及管理组织形式的部分预设以下四种群组类型,可以适应各种群聊场景需求。好友工作群(Work):类似普通微信群,创建后仅支持已在群内的好友邀请加群,且无需被邀请方同意或群主审批。陌生人社交群(Public):类似QQ群,创建后群主可以指定群管理员,用户搜索群ID发起加群申请后,需要群主或管理员审批通过才能入群。临时会议群(Meeting):创建后可以随意进出,且支持查看入群前消息;适合用于音视频会议场景、在线教育场景等与实时音视频产品结

  • Caused by: org.hibernate.HibernateException: Unanticipated return type [java.lang.Long] for UUID ...

    代码packagecom.ak47.cms.cms.entity importorg.hibernate.annotations.GenericGenerator importjava.util.* importjavax.persistence.* @Entity @Table(indexes=arrayOf(Index(name="idx_category",columnList="category"))) classTree{ @Id @GeneratedValue(strategy=GenerationType.AUTO,generator="custom-uuid") @GenericGenerator(name="custom-uuid",strategy="com.ak47.cms.cms.tree.CustomUUIDGenerator") varid:Long=0 varparentId:Long=0 @Column(length=200) varname=&q

  • 【SpringBoot guides系列翻译】调度任务

    原文调度任务用spring实现一个任务调度。你将做的你将做一个应用每5秒钟打印当前时间,用@Scheduled注解。你需要啥15分钟文本编辑器或者IDEJDK1.8+Gradle4+或Maven3.2+你可以把代码直接导入到IDE里面如何完成选择走Maven的方式创建目录结构通过mkdir-psrc/main/java/hello创建文件夹。创建pom.xml文件<?xmlversion="1.0"encoding="UTF-8"?> <projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion

  • Spring cache 理解

    今天在做项目的时候,有个用户的名字怎么刷新都拿不到,因为公司使用的是微服务,而且各个服务端之间有各自的缓存redis,因此,查了3个微服务,而且把相关的rediskey值清空掉,依旧是没有效果,最后有个眼尖的同事发现我这边的代码里有@Cacheable这货存在,应该是别的同事优化接口的时候加上的,导致没有处理Spring缓存,既然看到了这个API,当然要理解一番,要不浪费这么多时间呢。SpringcacheSpring自3.1版本引入了==注解缓存==,也就是我们通常说的Springcache,这里我们要注意下,Spring的缓存与我们通常意义上的缓存差别很多,他不是一个具体的实现方案,而是对缓存的一种操作方法,为什么这么说呢?这是Spring自带的,并没有相关的持久性方法之类这是作为一种框架对缓存的使用,不能大规模的在项目中替换诸如redis之类的缓存最后一点,也就是最重要的,Springcache是基于AOP的,所以一旦项目停掉或者重启,那么我们的缓存也就没有了,更别提容灾了,所以场景适合才是最重要的。==因为是基于AOP,所以在方法内部或者非public方法不支持==废话说完,我

  • 牛客网 计算机网络 选择题及知识点 (1)

    ARP 的功能是将IP地址解析为MAC地址。A.正确 B.错误复制解析:ARP 协议(AddressResolutionProtocol),或称地址解析协议。在以太网链路上仅仅知道某台主机的IPaddress,并不能立即将封包传送过去,必须先查明该主机的实体位(Physicaladdress/MACaddress)才能真正发送出去,而ARP协议的功用就是在于将IPaddress转换成实体位址,查询目标设备的MAC地址,以保证通信的顺利进行。并且只能在区域网路内使用,解析网路装置的MAC位址,ARP是TCP/IP设计者利用乙太网的广播性质,设计出来的位址解释协定;它的主要特性和优点是它的位址对应关系是动态的,它以查询的方式来获得IP位址和实体位解析:Connection:   连接方式,   Close   表明为非持续连接方式,   keep-alive   表示持续连接方式。 Cookie   值是由服务器产生的,   HTTP  请求报文中有   Cookie   报头表示曾经访问过 www.test.edu.cn   服务器。解析:TopLevelDomain顶级域名它是一个因

  • Jenkins部署码云SpringBoot项目到远程服务器

    本文是上一篇文章的后续,上一篇只是利用Jenkins部署项目到本地,并启动,本文是将项目部署到远程服务器并执行。 1.环境准备1.1安装插件上一篇文章已经介绍了需要安装的应用及插件,这一篇还需要2个插件,分别是如下插件:GitParameterPlug-In:这个插件用于获取git上信息,如分支和标签PublishOverSSH:这个插件用于将本地文件发送到远程服务器1.2环境配置这里需要在系统管理->系统设置->PublishoverSSH配置远程部署的服务器,如图:其中参数配置如下:Passphrase:远程服务器密码Name:这个就是给远程连接起个名Hostname:远程服务器地址Username:远程服务器用户名RemoteDirectory:上传文件路径都配置完成后可以点击下面TestConfiguration进行测试,如果提示Success则证明配置成功。2.项目配置这里大致分为四个部分2.1参数首先是参数,基本上和上一篇差不多,新增了几个,有一个和之前的不一样,使用的GitParameter,这里选择的分支(branch),如下图:2.2Gitgit没什么好说

  • Jquery的属性操作和DOM操作

    JQ中非常重要的部分,就是操作DOM的能力 一 属性操作1text():获取或设置某个文本属性      2html()  :获取或设置某个元素属性    3val()  :  获取或设置表单内容  (原生JS使用value)    4 attr() :获取或设置匹配元素的属性和值        $(selector).attr(xxx) :返回被选元素的属性        $(selector).attr(xxxx,xxxx) :设置被选元素的属性和值,第一个参数为被选中的属性,第二个参数为属性值        $(selector).attr(xxx,function(index,value)) :利用函数来设置属性值,要return返回     5css() :设置或获取元素的css属性    1  获取CSS属性值:$().css(“属性”)        2  设置单个CSS属性:$().css(“属性”,“属性值”)    3  设置多个CSS属性:$().css({“属性1”:”参数1”,”属性2”:”参数2”,”属性3”:”参数3”})    6css类操作     1

  • 不用加减乘除做加法

    题意写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。样例对于num1=15,num2=17,返回32。思路位运算首先先来看下十进制是如何计算的:相加各位的值,不进位,结果是22,(5+7=12,舍弃进位就是2,1+1=2没有进位就是22)计算进位值,得到10。然后将上述两步得到的值重复步骤1和2。直到进位置为0,返回不进位的值即可。那么对于二进制也可以用这种方式计算:相加各位的值,不进位,15(1111)+17(10001)=11110,其实就是将不同的位保留,相同的位归0,那么这正是位运算中的异或运算的规则,所以15^17即可得到不进位的值。计算进位置其实就是将只保留相同的位,也就是15(1111)+17(10001)=00001,既然是进位值,还应该左移一位,也就是00010,这两个小操作对应的就是位运算中的&和<<,即(num1&num2)<<1。然后将上述两步得到的值重复步骤1和2。直到进位置为0,返回不进位的值即可。BigIntegerJava对于高精度运算有一个类是BigInteger,其中有一个add(

  • Blender、Maya、C4D哪个最适合做3D动画?

    写在前面:关于哪个软件更容易学,其实把其中的一个学专学精了都会比较吃香,建议初学者先考虑清楚今后要从事的职业和发展方向,再有针对性的精修;这里答主把Maya也加进来对比,仅供参考~Blender、Maya、C4D三款软件都是三维制作软件。大致的功能和可以胜任的工作基本相差不多,在界面和操作中稍有不同,其擅长的领域也有略微差别Maya也可以说是一个资源整合平台,主要应用于影视类动画的制作及相关资源的整合。Maya的三维动画、建模、仿真和渲染模块提供了一个功能强大的集成工具集。可用于动画、环境、运动图形、虚拟现实和角色创建。在各大电影屏幕中我们都可以看到maya的身影。C4D全名CINEMA4D,操作界面清爽,新手相对比较容易上手的。C4D可与AE进行无缝衔接,在AE中直接导入C4D的场景使用,所以在小短片、影视包装的制作中,c4d还是很受青睐的。C4D一大特点就是集成包裹。在栏目包装,电视台、影视后期、广告、特效等方向表示不错,常和剪辑和特效软件配合使用,C4D涉及的领域除了运动图形图像,也涉及建筑表现,角色动画,以及电影后期制作。在集成的功能有一些是后期软件的功能,例如三维和2D的追踪

  • 动态 | 谷歌语义理解框架SyntaxNet升级 开启无数可能性

    在AI语义理解领域,谷歌一直不遗余力地进行研发投入。对于普通用户而言,2015年发布的基于深度神经网络的谷歌智能邮件回复,2016年上线的神经机器翻译系统(GNMT),便源自于谷歌在该领域的研究成果。在消费级产品之外,谷歌还持续为AI开发者提供技术支持,不断推出新的开源工具。去年夏天,针对语句的语法结构分析,谷歌开源了SyntaxNet神经网络框架,以及与之搭配英语分析预训练模型ParseyMcParseface。紧随其后,谷歌发布了针对其他40门语言的语法分析模型。并将它们命名为Parsey'sCousins(即“Parsey的表兄妹们”)。对英语国家开发者而言,为英语之外的语言开发机器学习系统是一件相当不容易的事。现在,经过将近一年的努力,谷歌推出了SyntaxNet框架以及Parsey相关模型的升级版。SyntaxNet升级就雷锋网所知,这是SyntaxNet自诞生以来的最重大升级。这建立在谷歌对各语言的语义理解研究基础之上。此次升级的核心是一项新技术:能对输入语句的多层表示进行很好的学习。具体来讲,它延伸了TensorFlow,能对多层语言结构进行合成建模,还能够在语

  • 腾讯云互动白板设置白板推流回调地址api接口

    1.接口描述接口请求域名:tiw.tencentcloudapi.com。 设置白板推流回调地址,回调数据格式请参考文档:https://cloud.tencent.com/document/product/1137/40257 默认接口请求频率限制:20次/秒。 APIExplorer提供了在线调用、签名验证、SDK代码生成和快速检索接口等能力。您可查看每次调用的请求内容和返回结果以及自动生成SDK调用示例。 2.输入参数以下请求参数列表仅列出了接口请求参数和部分公共参数,完整公共参数列表见公共请求参数。 参数名称 必选 类型 描述 Action 是 String 公共参数,本接口取值:SetWhiteboardPushCallback。 Version 是 String 公共参数,本接口取值:2019-09-19。 Region 是 String 公共参数,详见产品支持的地域列表。 SdkAppId 是 Integer 客户的SdkAppId Callback 是 String 白板推流任务结果回调地址,如果传空字符串会删除原来的回调

  • 函数式编程

    在了解函数式编程之前,我们先看看命令式编程。 就像在英语中,命令式时态用于给出命令,编程中的命令式是给计算机一组语句来执行任务。 这些语句通常会改变程序的状态,例如更新全局变量,典型的例子就是写一个for循环。 声明并定义一个变量,判断变量并循环遍历操作。相信很多同学在大一学C的时候对这一点深有体会了。 相反,函数式编程是声明式编程的一种形式,通过调用方法或函数来告诉计算机要做什么。   函数式编程中一个核心概念就是纯函数,如果一个函数满足以下几个条件,就可以认为这是个纯函数了: 它是一个函数; 当给定相同的输入(函数的参数)的时候,总是有相同的输出(返回值); 没有副作用; 不依赖于函数外部状态。 JavaScript提供了许多处理常见任务的方法(API),所以我们不用写出计算机该如何执行它们。 例如,你可以用map函数替代上面提到的for循环来处理数组迭代。这有助于避免语义错误。 (map()函数的一个参数是自定义每一项遍历的形参名,另一参数为一个函数方法,返回一个新数组, 数组中的元素为原始数组元素调用函数处理后的值。通常情况下,map()不会改变原始数组。) &n

  • Sublime Text 使用介绍、全套快捷键及插件推荐

    开篇:如果说Notepad++是一款不错Code神器,那么SublimeText应当称得上是神器滴哥。SublimeText最大的优点就是跨平台,Mac和Windows均可完美使用;其次是强大的插件支持,几乎无所不能。开始使用SublimeText:SublimeText有Dev版本,推荐使用,下载地址,一般推荐下载便携版本(Portableversion),这样拿来拿去很方便,也不用安装,而且插件和主体在一个目录下,便携。相关阅读:大前端推荐使用的前端开发工具推荐轻量级开发软件Notepad++及其两款超强辅助插件SublimeText快捷键:Ctrl+Shift+P:打开命令面板Ctrl+P:搜索项目中的文件Ctrl+G:跳转到第几行Ctrl+W:关闭当前打开文件Ctrl+Shift+W:关闭所有打开文件Ctrl+Shift+V:粘贴并格式化Ctrl+D:选择单词,重复可增加选择下一个相同的单词Ctrl+L:选择行,重复可依次增加选择下一行Ctrl+Shift+L:选择多行Ctrl+Shift+Enter:在当前行前插入新行Ctrl+X:删除当前行Ctrl+M:跳转到对应括号Ctr

  • 交换机telnet配置

    新开箱交换机开机配置Telnet需要三个步骤: 1.开启telnet是能:系统视图模式下输入命令:telnetserverenable#开启telnet功能# 2.Telnet创建账号:aaa模式下:local-useradminpasswordcipheradminprivilegelevel15                            local-useradminservice-typetelnet 3.VTY中设置账号认证与允许Telnet接入:user-interfacevty04#进入VTY模式#                 &nbs

  • fastlane问题汇总

    问题1:mac电脑fastlane打包app的时候报错: RequestedbutdidnotfindextensionpointwithidentifierXcode.IDEKit.ExtensionSentinelHostApplicationsforextension 应该是xcode插件相关导致的,最近升级了mac电脑的系统到monterey12.3.1系统。xcode升级到13.3版本。估计是这里某个原因导致,百度出来资料比较少。找到个类似的资料网址: 参考资料网址:https://www.jianshu.com/p/d936b525b83f 2022-04-0710:34:47.832xcodebuild[32177:129763]RequestedbutdidnotfindextensionpointwithidentifierXcode.IDEKit.ExtensionSentinelHostApplicationsforextensionXcode.DebuggerFoundation.AppExtensionHosts.watchOSofplug-incom.ap

  • 树的重心及其性质

    性质:   1.删除重心后所得的所有子树,节点数不超过原树的1/2,一棵树最多有两个重心;   2.树中所有节点到重心的距离之和最小,如果有两个重心,那么他们距离之和相等;   3.两个树通过一条边合并,新的重心在原树两个重心的路径上;   4.树删除或添加一个叶子节点,重心最多只移动一条边;     5.一棵树最多有两个重心,且相邻。 证明:https://www.cnblogs.com/suxxsfe/p/13543253.htm   附一个求树的重心的板子题:CodeforcesRound#670(Div.2)  C.LinkCutCentroids #include<bits/stdc++.h> #definerep(i,n)for(inti=0;i!=n;++i) #defineper(i,n)for(inti=n-1;i>=0;--i) #defineRep(i,sta,n)for(inti=sta;i!=n;++i) #definerep1(i,n)for(inti=1;i

  • 博客中 Flex4/Flash mp3音乐播放器实例 含演示地址

    要求 必备知识 本文要求基本了解AdobeFlex编程知识和JAVA基础知识。 开发环境 MyEclipse10/FlashBuilder4.6/FlashPlayer11及以上 演示地址 演示地址资料下载   播放器演示已经在博客banner部分给出了,下面还是上一截图吧:   下面是程序的核心业务代码: <?xmlversion="1.0"encoding="utf-8"?> <s:Applicationxmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="330"height="75"backgroundAlpha="1.0"backgroundColor="#9C4B4B" preloaderChromeColor="#060606" creationComplete="initApp()"> &l

  • bzoj3205: [Apio2013]机器人

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3205 思路:类似斯坦纳树的想法 但是因为这里的合并必须连号 所以子集枚举就变成了区间合并 说说做法好了 首先记搜搜出每个点向四个方向走一步会到哪里 注意:转向器可能导致机器人一直在里面转出不来,要特判掉 然后设f[l][r][x][y]表示当前合并的机器人是[l,r],合并点是(x,y) 两种转移: 枚举子区间,合并f[l][r][x][y]=min(f[l][mid][x][y],f[mid+1][r][x][y]) 从另一个地方转移过来f[l][r][x][y]=min(f[l][r][xx][yy])(xx,yy)走一步能到(x,y) 然后还不够 第二种转移的spfa要加一个杂技优化 “ 观察这个图发现所有边的边权都是1如果是单源的话SPFA可以进化成广搜 现在是多源因此我们可以这样做: 维护两个队列,将初始所有的点按照距离排序后从小到大加入队列1 每次拓展出的点加入队列2 每次取出点的时候,如果队列1队尾元素的距离小于队列2就把队列1的队尾元素拿去松弛

相关推荐

推荐阅读