本文为原创,转载请注明:http://www.cnblogs.com/kylewilson/

题目出处:

https://www.vijos.org/p/1057

题目描述:

给一个N*M的土地,由0和1表示,0表示瑕疵,1表示完好,找出最大的完好的正方形土地?

输入:

输入文件第一行为两个整数n,m(1<=n,m<=1000),接下来n行,每行m个数字,用空格隔开。0表示该块土地有瑕疵,1表示该块土地完好

4 4

0 1 1 1

1 1 1 0

0 1 1 0

1 1 0 1

思路分析:

首先看数据范围,1~1000,存储地图需要O(n*m)的内存空间,空间复杂度可控;再看时间复杂度,遍历所有点为O(n*m);

为什么要先分析空间及时间复杂度呢?因为很多时候,数据规模就决定了算法,如果数据规模为1~1000000000,你还会考虑O(n*n)的算法吗,肯定不会,这种数据一看就知道最优解法为线性复杂度O(n)的算法;

列举如下3处情况:图中彩色方框都为1,白色方框都为0

假设地图中存在一个最大的正方形,则该正方形存在一个右下角P点,且该点为1;

如果当某一个点P(i,j)为0时,则以该点为右下角不存在正方形,所以该点也不可能在最大的正方形中。

不同情况列举:

图P1.1

当P(i,j)=1时,可以看出以P为右下角,最优解由红色边长决定,即以P点为起点,向左连续为1的最多个数,木桶原理

图P1.2

当P(i,j)=1时,可以看出以P为右下角,最优解由紫色边长决定,即以M点为右下角能组成的最大的正方形

图P1.3

当P(i,j)=1时,可以看出以P为右下角,最优解由绿色边长决定,即以P点为起点,向上连续为1的最多个数

则可以建立如下DP公式

设f[i][j]:以点(i,j)为右下角,能组成的最大正方形边长

left[i][j]:以点(i,j)为起点,向左最大连续1的个数,提前初始化

up[i][j]:以点(i,j)为起点,向上最大连续1的个数,提前初始化

f[i][j]=max(f[i-1][j-1]+1, left[i][j], up[i][j])

注:地图为一行或者一列时,提前预处理,方便后面递推

C++源码如下:

github: https://github.com/Kyle-Wilson1/Vijos/tree/master/P1057

  1. #include <iostream>
  2. #include <fstream>
  3. #include <vector>
  4.  
  5. using namespace std;
  6.  
  7. struct Node {
  8. int left, up;
  9. };
  10.  
  11. int main() {
  12. ifstream cin("a.in");
  13. ofstream cout("a.out");
  14.  
  15. vector<vector<int>> f(1000, vector<int>(1000, 0));
  16. vector<vector<int>> map(1000, vector<int>(1000, 0));
  17. Node initNode{0, 0};
  18. vector<vector<Node>> node(1000, vector<Node>(1000, initNode));
  19.  
  20. int n, m, i, j, maxSquare = 0;
  21.  
  22. cin >> n >> m;
  23. //input
  24. for (i = 0; i < n; i++)
  25. for (j = 0; j < m; j++)
  26. cin >> map[i][j];
  27.  
  28. //init left
  29. for (i = 0; i < n; i++)
  30. for (j = 0; j < m; j++) {
  31. if (j == 0) {
  32. if (map[i][j] == 1) {
  33. node[i][j].left = 1;
  34. } else { node[i][j].left = 0; }
  35. } else {
  36. if (map[i][j] == 1) {
  37. node[i][j].left = node[i][j - 1].left + 1;
  38. } else {
  39. node[i][j].left = 0;
  40. }
  41. }
  42. }
  43.  
  44. //init up
  45. for (j = 0; j < m; j++)
  46. for (i = 0; i < n; i++) {
  47. if (i == 0) {
  48. if (map[i][j] == 1) {
  49. node[i][j].up = 1;
  50. } else { node[i][j].up = 0; }
  51. } else {
  52. if (map[i][j] == 1) {
  53. node[i][j].up = node[i - 1][j].up + 1;
  54. } else {
  55. node[i][j].up = 0;
  56. }
  57. }
  58. }
  59.  
  60. auto maxOfTwo = [](int a, int b) { return a > b ? a : b; };
  61. auto minOfThree = [](int a, int b, int c) { return a < b ? a < c ? a : c : b < c ? b : c; };
  62.  
  63. //dynamic programming
  64. for (i = 0; i < n; i++) {
  65. if (map[i][0] == 1) {
  66. f[i][0] = 1;
  67. maxSquare = 1;
  68. } else f[i][0] = 0;
  69. }
  70.  
  71. for (j = 1; j < m; j++) {
  72. if (map[0][j] == 1) {
  73. f[0][j] = 1;
  74. maxSquare = 1;
  75. } else f[0][j] = 0;
  76. }
  77.  
  78. for (i = 1; i < n; i++)
  79. for (j = 1; j < m; j++) {
  80. f[i][j] = minOfThree(node[i][j].left, node[i][j].up, f[i - 1][j - 1] + 1);
  81. maxSquare = maxOfTwo(f[i][j], maxSquare);
  82. }
  83.  
  84. cout << maxSquare;
  85. cin.close();
  86. cout.close();
  87. return 0;
  88. }

Vijos-P1057题解的更多相关文章

  1. 区间 (vijos 1439) 题解

    [问题描述] 现给定n个闭区间[ai,bi],1<=i<=n.这些区间的并可以表示为一些不相交的闭区间的并.你的任务就是在这些表示方式中找出包含最少区间的方案.你的输出应该按照区间的升序排 ...

  2. vijos题解

    Vijos题解 题库地址:https://vijos.org/p P1001 谁拿了最多奖学金 题意:按照指定要求计算奖学金,直接用if判断即可 #include<iostream> us ...

  3. [题解]vijos & codevs 能量项链

    a { text-decoration: none; font-family: "comic sans ms" } .math { color: gray; font-family ...

  4. [题解]vijos 运输计划

    Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球.小 P 掌管一家 ...

  5. 集合删数 (vijos 1545) 题解

    [问题描述] 一个集合有如下元素:1是集合元素:若P是集合的元素,则2 * P +1,4*P+5也是集合的元素,取出此集合中最小的K个元素,按从小到大的顺序组合成一个多位数,现要求从中删除M个数位上的 ...

  6. 洛谷P1057传球游戏题解

    题目 这个题表面上看并不像DP,但是当我们看到方案数时,我们可能会想到什么??? 对,分类加法原理,在每一轮中,每一个点的方案数都要加上这个点左边的方案与右边的方案. 因此我们可以枚举,设一个DP数组 ...

  7. 小胖守皇宫(VIJOS P1144 )题解

    题目描述 huyichen世子事件后,xuzhenyi成了皇上特聘的御前一品侍卫. 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状:某些宫殿间可以互相望见.大内保卫森严,三步一岗,五步一哨,每 ...

  8. vijos P1915 解方程 加强版

    背景 B酱为NOIP 2014出了一道有趣的题目, 可是在NOIP现场, B酱发现数据规模给错了, 他很伤心, 哭得很可怜..... 为了安慰可怜的B酱, vijos刻意挂出来了真实的题目! 描述 已 ...

  9. 【BZOJ 1065】【Vijos 1826】【NOI 2008】奥运物流

    http://www.lydsy.com/JudgeOnline/problem.php?id=1065 https://vijos.org/p/1826 好难的题啊TWT ∈我这辈子也想不出来系列~ ...

  10. Vijos1448校门外的树 题解

    Vijos1448校门外的树 题解 描述: 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的…… 如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现 ...

随机推荐

  1. 自学Python5.3-内置模块(1)

    内置模块(1)内置模块是Python自带的功能,在使用内置模块相应的功能时,需要  先导入 再 使用  1.OS模块       用于提供系统级别的操作: os.getcwd() 获取当前工作目录,即 ...

  2. 深入理解计算机系统_3e 第七章家庭作业 CS:APP3e chapter 7 homework

    7.6 +-----------------------------------------------------------------------+ |Symbol entry? Symbol ...

  3. 安装Redis后RedisDesktopManager无法连接

    1.查看端口,发现端口不通 2.修改安装redis的目录的redis.conf文件,把bind改为虚拟机的本机ip 3.关闭虚拟机的防火墙 #1.查看防火墙状态[root@localhost src] ...

  4. 修改Intellij IDEA中工程对应的Java SDK、Scala SDK

    如果编译Scala工程时,遇到如下异常: can't expand macros compiled by previous versions of Scala 很可能是工程的scala版本,和依赖的包 ...

  5. jemeter工作台设置

    工作台的设置 1.创建一个线程组 创建一个http代理服务器:工作台-->添加-->非测试元件-->http代理服务器 设置参照下图,要录制的时候点击启动 2.设置IE浏览器 IE- ...

  6. sharepreference使用教程

    1.应用 SharePreference主要用于保存一些数据,比如用户登录后的user_id,user_mobile,这样就可以做自动登录了,每次判断SharePreference中有没有数据,有的话 ...

  7. 用VS2015写一个简单的ASP.net网站

    第一步:打开VS2015,然后新建一个空的解决方案,其中解决方案的名称WebSiteTest可类似认为是本次网站的名称,系统会以该名称(WebSiteTest)生成一个文件夹,在WebSites文件夹 ...

  8. C++11新语法糖之尾置返回类型

    C++11的尾置返回类型初衷是为了方便复杂函数的声明和定义,但是当复杂度稍微提升一些的时候很明显能注意到这种设计的作用微乎其微. 首先考虑如下代码: C++ //返回指向数组的指针 auto func ...

  9. SpringMVC总结

    本文是对慕课网上"搞定SSM开发"路径的系列课程的总结,详细的项目文档和课程总结放在github上了.点击查看 MVC简介 Model-View-Control,MVC是一种架构模 ...

  10. bzoj 2337: [HNOI2011]XOR和路径

    Description Input Output Sample Input Sample Output HINT Source Day2 终于把这个史前遗留的坑给填了... 首先异或的话由位无关性,可 ...