本文为原创,转载请注明: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

#include <iostream>
#include <fstream>
#include <vector> using namespace std; struct Node {
int left, up;
}; int main() {
ifstream cin("a.in");
ofstream cout("a.out"); vector<vector<int>> f(1000, vector<int>(1000, 0));
vector<vector<int>> map(1000, vector<int>(1000, 0));
Node initNode{0, 0};
vector<vector<Node>> node(1000, vector<Node>(1000, initNode)); int n, m, i, j, maxSquare = 0; cin >> n >> m;
//input
for (i = 0; i < n; i++)
for (j = 0; j < m; j++)
cin >> map[i][j]; //init left
for (i = 0; i < n; i++)
for (j = 0; j < m; j++) {
if (j == 0) {
if (map[i][j] == 1) {
node[i][j].left = 1;
} else { node[i][j].left = 0; }
} else {
if (map[i][j] == 1) {
node[i][j].left = node[i][j - 1].left + 1;
} else {
node[i][j].left = 0;
}
}
} //init up
for (j = 0; j < m; j++)
for (i = 0; i < n; i++) {
if (i == 0) {
if (map[i][j] == 1) {
node[i][j].up = 1;
} else { node[i][j].up = 0; }
} else {
if (map[i][j] == 1) {
node[i][j].up = node[i - 1][j].up + 1;
} else {
node[i][j].up = 0;
}
}
} auto maxOfTwo = [](int a, int b) { return a > b ? a : b; };
auto minOfThree = [](int a, int b, int c) { return a < b ? a < c ? a : c : b < c ? b : c; }; //dynamic programming
for (i = 0; i < n; i++) {
if (map[i][0] == 1) {
f[i][0] = 1;
maxSquare = 1;
} else f[i][0] = 0;
} for (j = 1; j < m; j++) {
if (map[0][j] == 1) {
f[0][j] = 1;
maxSquare = 1;
} else f[0][j] = 0;
} for (i = 1; i < n; i++)
for (j = 1; j < m; j++) {
f[i][j] = minOfThree(node[i][j].left, node[i][j].up, f[i - 1][j - 1] + 1);
maxSquare = maxOfTwo(f[i][j], maxSquare);
} cout << maxSquare;
cin.close();
cout.close();
return 0;
}

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. iOS 内存泄漏排查以及处理

    使用Xcode7的Instruments检测解决iOS内存泄露   文/笨笨的糯糯(简书作者)原文链接:http://www.jianshu.com/p/0837331875f0作为一名iOS开发攻城 ...

  2. MySQL创建用户与授权方法

    最近在弄个mysql兼职项目,记录一下: 一, 创建用户: 命令:CREATE USER 'username'@'host' IDENTIFIED BY 'password'; 说明:username ...

  3. sharepreference使用教程

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

  4. Who's in the Middle

    FJ is surveying his herd to find the most average cow. He wants to know how much milk this 'median' ...

  5. vmstat 命令详解

    作用:vmstat 的含义为显示虚拟内存状态(virtual memor statics),但是它可以报告关于进程,内存,I/O 等系统整体运行状态 选项: -a 显示活动内页 -f 显示启动后创建的 ...

  6. du 命令详解

    du : show disk usage  作用:统计目录或文件所占用磁盘空间的大小. 语法:du 参数 选项 参数: -a 为每个制定文件显示磁盘使用情况, 或者为目录中每个文件显示各自磁盘使用情况 ...

  7. Saltstack的安装和配置

    1.安装salt 因为系统自带的yum源不支持saltstack安装包的支持,所以需要安装第三方yum源(epel) # yum -y install epel-release salt分为主服务器( ...

  8. c#全宇宙最牛的编程软件

    c#走的道路!PC,PD,电脑一体,一个账户就可以三合一,可以跨平台的编程,在未来的道路如果微软能一直走下去,那么c#将成为宇宙最牛B的编程软件.

  9. 20行JS代码实现贪吃蛇

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. MFC鼠标单击截获鼠标双击事件,且无法记录单击的数据的解决方案

    遇到的问题: 鼠标点击会截断鼠标双击的事件,无法保存椭圆的数据.也就是说双击执行的过程是OnLButtonDown,OnLButtonUp,OnLButtonDblClk,OnLButtonUp.并不 ...