题目描述

  题目建立上一个作业的题目基础上,上一次作业是要求在一个一维序列里找一个最大连续子串,这次task最基础的要求是在一个二维表里找一个最大连续子矩形,但是这次作业有若干个升级版,分别要求可以加入运行参数[\h][\v][\a],其中\h选项代表给定的二维表是水平循环的,\v代表给定的二维表是水平循环的,\a表示结果可以突破矩形的限制,寻找一个最大的连通块,而非矩形。

我的思路

  这次题目最难的一部分是实现/a的操作,相比之下其他要求实现比较简单,先从简单的说起。

  从二维表里找一个最大的子矩形,这和一维的情况非常类似,这促使我们思考如何将这种情况转化到一维的情况,我们观察二维表中的任意一个子矩形。

  我们可以发现子矩形只是选中了一些连续的子列,每个子列的始终位置都是相同的,而且每个子列的值都不会影响其他子列的值,这样我们把子列的值得的和作为一个元素,就得到了一个一维序列。

  这时就可以使用在作业毅力的算法来处理这种状态,考虑到要遍历到所有情况,我们仅需要枚举行上每个行之间的区间,时间复杂度为O(n^2),然后再用homework-01里方法处理两行之间的数据即可,时间复杂度为O(m),总时间复杂度为O(n^2m),这样这道题目就比较好的解决了。不过我们并不能确定这个问题时间复杂度下界就是O(n^2m),找出一个O(nm)的算法还是非常有吸引力的,毕竟这和一维的情况存在更多的一致性。

  有了上面的基础我们再考虑/v和/h的情况,这两种情况实际上是等价的,因此我们仅考虑/h的情况,/h选项表示二维表在水平方向上时循环连通的,我采用了在水平方向上扩展一次二维表的方法,扩展如下图

  扩展之后我们在n*m的矩阵的基础上得到了一个n*2m的矩阵上进行同样的算法,这时还需要加一个限制,考察一行发现如果覆盖整个一行的列长超过m的话会在当前解中加入重复的元素,我们此时枚举列的起始位置,同时保证列长为m即可,这样的时间复杂度为O(n^2m^2),还是一个非常理想的时间复杂度。

  最后我们来讨论一下/a选项,它要求找一个任意的最大联通块即可,这个问题难度很高(因为我想了好几天都没想到一个好的解法),题目要求的矩阵最大规模为32*32,初看这个规模显得非常小,但是对于这道题目我们难以找到一个多项式的解,今天在课上也确认了这确实是一个NP问题,解决这个问题有很多思路,这里我们简单讨论几种思路,从经验上我们可以发现如果一个非负的格子在最终解里,那么它相邻的非负格子也一定在最终解里,这样考虑的话就把我们生成矩阵中的所有非负连通块,最终解一定是某些块的集合加入它们之间相连的负的格子,我们枚举这样的集合,然后判断集合里的块是否能相连,具体方法为从一个块中向外遍历负格子,如果遍历的路径和的绝对值已经比该块大了,就停止遍历,可以使用记忆化来优化一下,如果能遍历的目标块就找一条最小的(同时要看这条路的绝对值和是否也比目标块小),这时把这两块连成一块,继续连接其他块,考虑每一种情况后取一个最优值,视为找到的一个解,这个方案的优点是能较快的找到一个好的近似解,缺点是代码复杂,难以实现,而且它目前仅能求一个近似解,并不能证明它是最优的,不满足题目要求。再考虑另一种方法,状态压缩动态规划,状压DP将每一行压为一个状态,这个状态用一个r进制数表示,由于本题要求找到的块具有连通性,那么我们需要一个m进制的数来维护连通性,但本题目有一定特殊性,如果把它视作插头Dp的话这是一个4插头DP也就是说如果相邻两个格子都被选中的话那么他们一定联通的(感谢Tony Shaw的指导),这样考虑的话仅需m/2进制就可以满足需求,我们仅需维护我们当前状态里没有不与当前行连通的块,并且用每一个只有一个块的状态去更新最终解,这样就能很好地解决问题。这个方案的优点是思路清晰,代码相对好写(实际上实现也相当困难),确定是时间复杂度高,我们假定矩阵的规模满足m < n,那么我们的复杂度为O(n(m/2)^(2m)),利用轮廓线优化可以得到O(nm(m/2)^m)的复杂度,题目限制是(n,m)<=(32,32),最坏情况下该算法的规模为32*32*16^32,这个复杂度实在难以接受,但是如果我们考虑一种特例——矩阵的一个维度特别小,那么这种方法就有很大的优势。

一些收获

  经过一晚上的奋斗成功在VS2012下完成了performance analyze 和 unit test,第一次做这个非常吃力,但是还是颇有收获,先看看unit test。

  写了三个测试方法,分别测试了三个选项以及基础情况的输出,使用了三个不同的测试样例,这次为了能更快进行一些初步的unit test实战,没有对数据进行容错处理,所以样例规模都很小,其中TestACondition我只是采用了找一个最大非负连通子块的方法来代替,所以最后的结果只是一个近似值,如果在assert宏里加入容限就能通过test。再看看测试的覆盖率。

  这个工程我写了一部分函数来模块化,从上表看代码有效性还是很高的,但我初学单元测试,还不是很好的看懂覆盖图。

  完成第一次单元测试后,个人感觉单元测试这个工具非常有用,但是需要很大的精力维护,它可以很好的维护代码的正确性,单元测试可能非常依赖于测试样例,管理好测试用例对于单元测试是一个重要的组成部分,编写单元测试可能还要遵循简短的方法,我在写单元测试时已经有了一个单元测试的单元测试,但我认为这样的代价是不值得的,好的单元测试应该逻辑清晰而简洁,具有非常好的可读性,以便于维护。

  这次单元测试我但我耽误时间最多的是配置过程,这里有一个小细节,使用VS2012单元测试时原工程一定要导出一个DLL作为symbol才能正常连接,不过这短时间也让我熟悉了下VS中solution-projects的文件结构,感觉这个结构非常舒服,可以加入很多工具配合在一起使用同一管理,很赞一点设计。

  最后看一下performance analyze

  performance analyze做起来就太傻瓜化了,一键完成,不过还是学到了新工具,性能分析我使用了一个500*500的大矩阵,矩阵的元素为16位整型范围内,从上图可以看到主要的运算集中在算法模块,我在算法实现上确实牺牲一部分时间系能,程序还能采用空间换时间的方法继续优化,不过都是只是常数上的,而且会破坏代码结构,于是没有进一步优化。

  

homework-02 最大子区域和的更多相关文章

  1. 实现步骤: 推送&传感器&UIDynamic

    一.本地通知基本使用: #01.请求授权(8.0以前默人授权) #02.创建本地通知 #03.设置通知内容 #04.设置通知时间(多久后发通知) #05.发送通知 二.本地通知而外设置: #01.设置 ...

  2. Mask RCNN 学习笔记

    下面会介绍基于ResNet50的Mask RCNN网络,其中会涉及到RPN.FPN.ROIAlign以及分类.回归使用的损失函数等 介绍时所采用的MaskRCNN源码(python版本)来源于GitH ...

  3. plot-sin-02

    draw sin 02 设置数据区域的边界线颜色 设置坐标轴的位置 code #!/usr/bin/env python # -*- coding: utf-8 -*- import numpy as ...

  4. 363. 矩形区域不超过 K 的最大数值和(利用前缀和转化为最大子序和问题)

    题目: 链接:https://leetcode-cn.com/problems/max-sum-of-rectangle-no-larger-than-k/ 给定一个非空二维矩阵 matrix 和一个 ...

  5. day 02 ---class - homework

    # -*- coding: utf-8 -*-# @Time : 2018/12/20 14:34# @Author : Endless-cloud# @Site : # @File : day 02 ...

  6. ASP.Net MVC开发基础学习笔记:五、区域、模板页与WebAPI初步

    一.区域—麻雀虽小,五脏俱全的迷你MVC项目 1.1 Area的兴起 为了方便大规模网站中的管理大量文件,在ASP.NET MVC 2.0版本中引入了一个新概念—区域(Area). 在项目上右击创建新 ...

  7. ASP.NET MVC5 网站开发实践(二) Member区域 - 咨询管理的架构

    咨询.留言.投诉等功能是网站应具备的基本功能,可以加强管理员与用户的交流,在上次完成文章部分后,这次开始做Member区域的咨询功能(留言.投诉都是咨询).咨询跟文章非常相似,而且内容更少.更简单. ...

  8. ASP.NET MVC5 网站开发实践(二) Member区域 - 添加文章

    上次把架构做好了,这次做添加文章.添加文章涉及附件的上传管理及富文本编辑器的使用,早添加文章时一并实现. 要点: 富文本编辑器采用KindEditor.功能很强大,国人开发,LGPL开源,自己人的好东 ...

  9. ASP.NET MVC5 网站开发实践(二) Member区域 - 文章管理架构

    上次把member的用户部分完成,现在开始做文章管理部分.文章部分根据涉及显示现实文章列表,发布文章,修改文章,删除文章等功能.最终的实现目标是使用权限来控制用户是否能进行相应操作,管理员权限的会显示 ...

随机推荐

  1. linux scp

    scp是 secure copy的缩写, scp是linux系统下基于ssh登陆进行安全的远程文件拷贝命令.linux的scp命令可以在linux服务器之间复制文件和目录. scp命令的用处: scp ...

  2. Java的String、StringBuffer和StringBuilder的区别

    1.String 2.Stringbuffer 3.StringBuilder 4.三者之间的区别 5.使用策略 1.String public final class String implemen ...

  3. 构建linux内核源码树

    编写驱动程序时,需要内核源码树的支持.内核源码树时从内核源代码编译得到的.下面开始构造内核源代码的步骤.以Ubuntu为例子 1. 下载内源代码,位置www.kernel.org. (注意:源码树内核 ...

  4. 实现微信好友列表的php代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. [POJ3279]Fliptile(开关问题,枚举)

    题目链接:http://poj.org/problem?id=3279 题解:http://www.cnblogs.com/helenawang/p/5538547.html /* ━━━━━┒ギリギ ...

  6. Ubuntu下MySQL数据库安装与配置与卸载

    安装: sudo apt-get install mysql-server mysql-client 一旦安装完成,MySQL 服务器应该自动启动.您可以在终端提示符后运行以下命令来检查 MySQL ...

  7. TCSRM 593 div2(1000)(dp)

    Problem Statement      The pony Rainbow Dash wants to choose her pet. There are N animals who want t ...

  8. bzoj2797

    对和排序,显然最小是a1+a2,次小a1+a3 然后穷举哪里是a2+a3 这样a1,a2,a3就求出来了 注意a2+a3只可能是前n+1项中的一个,所以穷举这步是O(n)的 接下来我们把已经确定的数的 ...

  9. Java Web编程的主要组件技术——Hibernate入门

    参考书籍:<J2EE开源编程精要15讲> Hibernate是对象/关系映射(ORM,Object/Relational Mapping)的解决方案,就是将Java对象与对象关系映射到关系 ...

  10. 编译pure-ftpd时提示错误Your MySQL client libraries aren't properly installed

    如果出现类似configure: error: Your MySQL client libraries aren’t properly installed 的错误,请将mysql目录下的 includ ...