题目描述

  题目建立上一个作业的题目基础上,上一次作业是要求在一个一维序列里找一个最大连续子串,这次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. apk反编译(4)Smali代码注入

    转自 : http://blog.sina.com.cn/s/blog_5674d18801019i89.html 应用场景 Smali代码注入只能应对函数级别的移植,对于类级别的移植是无能为力的.具 ...

  2. 传感器(2)常用api简介及列出当前设备支持的传感器代码

    Android SDK提供了Android sensor framework,可以用来访问当前Android设备内置的传感器. ASF提供了很多类和接口,可以帮助我们完成各种与传感器有关的任务. 例如 ...

  3. iOS学习笔记: 使用CAShapeLayer创建带有空心区域的遮罩层

    CAShapeLayer是用来接受矢量Path,直接使用GPU来进行渲染的特殊图层.看下面效果: 对应代码: let markLayer = CAShapeLayer(); markLayer.fra ...

  4. Android百度地图

        帖子   热搜: 二维码 聊天 二维码扫描 传感器 游戏 定位 手势绘图 小项目 相框 绘图 涂鸦 拨打电话 记事本 定时器 通话记录 短信群发 listview 音乐播放器 项目例子 百度地 ...

  5. poj 1986 Distance Queries(LCA:倍增/离线)

    计算树上的路径长度.input要去查poj 1984. 任意建一棵树,利用树形结构,将问题转化为u,v,lca(u,v)三个点到根的距离.输出d[u]+d[v]-2*d[lca(u,v)]. 倍增求解 ...

  6. 推荐 15 个 Angular.js 应用扩展指令(参考应用)

    几天前我们看到Angular 1.4.0发布了-一个以社团为驱动的发布版本涵盖了400多个GitHub的提交,增加了对特性的提升,比如动画,以及可用性. 官方新闻发布稿 覆盖了绝大部分,这同样值得放于 ...

  7. Java [Leetcode 110]Balanced Binary Tree

    题目描述: Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced b ...

  8. linux中waitpid及wait的用法

    wait(等待子进程中断或结束) 表头文件      #include<sys/types.h>      #include<sys/wait.h> 定义函数 pid_t wa ...

  9. kettle连接hadoop&hdfs图文详解

    1 引言: 项目最近要引入大数据技术,使用其处理加工日上网话单数据,需要kettle把源系统的文本数据load到hadoop环境中 2 准备工作: 1 首先 要了解支持hadoop的Kettle版本情 ...

  10. android模块化app开发笔记-2插件间布局文件共享

    android编程时布局文件,图片资源等都是放在同一个文件夹下,这样照成一个问题就是我们想重用UI布局文件和图片时就还需要其分离这些资料,相信大部分android程序员都遇到过这样的问题,其痛苦程度不 ...