最大正方形--二维DP

题目描述

在一个n*m的只包含0和1的矩阵里找出一个不包含0的最大正方形,输出边长。

输入格式

输入文件第一行为两个整数n,m(1<=n,m<=100),接下来n行,每行m个数字,用空格隔开,0或1.

输出格式

一个整数,最大正方形的边长

输入输出样例

输入
4 4
0 1 1 1
1 1 1 0
0 1 1 0
1 1 0 1

输出
2

想了十几分钟没有想出来好的转移,看了题解真的是如拨云见日
我们在看过数据范围不难想到设二维状态f[i][j]那么这个状态肯定是要表示在i,j点时的最大矩阵,刚开始我想的是以i,j为右下角的矩阵内最大的1矩阵的大小,后来觉得不可行,因为无法知道矩阵内部的实际情况
既然如此,我们就把i,j作为信息,即设i,j为以i,j为右下角的1矩阵的最大长度
但是我们考虑转移,感觉一下不是很能想的出来,我就是在这里放弃了。
我们考虑对于一个点他是否能为其他矩阵做出贡献时的判断:
既然设i,j为右下角,那么我们就考虑把别的矩阵右下角转移成i,j的判断,那么显然有且仅有三个正方形能作为候选去向i,j转移,就是i,j的左边,右边和右上即 ( i − 1 , j ) , ( i , j − 1 ) , ( i − 1 , j − 1 ) (i-1,j),(i,j-1),(i-1,j-1) (i1,j),(i,j1),(i1,j1)三个点
那么我们考虑判断条件,我们可以依照样例输入看,如果要转移一个点,我们就要看这三点的矩阵大小,显然,如果大小不一,那么我们无法扩充为最大的,当三个大小相同,我们恰能扩充为一个更大的正方形 ,那么显然的是,在大小不一的时候,最小的一定是可以扩充的,因为两个大的能满足扩充最小的条件,于是我们就得到转移方程 f [ i ] [ i ] = m i n ( f [ i − 1 ] [ j ] , m i n ( f [ i ] [ j − 1 ] , f [ i − 1 ] [ j − 1 ] ) + 1 f[i][i] = min(f[i-1][j], min(f[i][j-1], f[i-1][j-1]) +1 f[i][i]=min(f[i1][j],min(f[i][j1],f[i1][j1])+1
在每个点比较最大值,输出最大值即可。

C o d e Code Code

#include<bits/stdc++.h>

#define N 101
#define gtc() getchar()
#define INF 0x3f3f3f3f
#define rg register

using namespace std;

template <class T>
inline void read(T &s){
	T w = 1, ch = gtc(); s = 0;
	while(!isdigit(ch)){if(ch == '-') w = -1; ch = gtc();}
	while(isdigit(ch)){s = s * 10 + ch - '0'; ch = gtc();}
	s = s * w;
}


int f[N][N], a[N][N];
int n, m;
 
int main()
{
	read(n), read(m);
		
	int ans = 0;
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j){
			read(a[i][j]);
			if(a[i][j] == 1) f[i][j] = min(f[i-1][j-1], min(f[i-1][j], f[i][j-1])) + 1;
			ans = max(ans, f[i][j]);
		}
	printf("%d\n", ans);
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
洛谷 P1681 最大正方形II 是一个动态规划问题,要求给定一个由 '0' 和 '1' 组成的矩阵,找出其中最大正方形,并输出其边长。 以下是一个 C++ 编写的解答示例: ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; int maximalSquare(vector<vector<char>>& matrix) { int rows = matrix.size(); if (rows == 0) return 0; int cols = matrix[0].size(); vector<vector<int>> dp(rows + 1, vector<int>(cols + 1, 0)); int maxSide = 0; for (int i = 1; i <= rows; i++) { for (int j = 1; j <= cols; j++) { if (matrix[i-1][j-1] == '1') { dp[i][j] = min(min(dp[i-1][j], dp[i][j-1]), dp[i-1][j-1]) + 1; maxSide = max(maxSide, dp[i][j]); } } } return maxSide * maxSide; } int main() { int n, m; cin >> n >> m; vector<vector<char>> matrix(n, vector<char>(m)); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cin >> matrix[i][j]; } } cout << maximalSquare(matrix) << endl; return 0; } ``` 在上述代码中,我们首先定义了一个名为 `maximalSquare` 的函数,该函数接受一个二维字符矩阵 `matrix` 作为参数,返回最大正方形边长。 在 `main` 函数中,我们首先从标准输入读取矩阵的行数和列数,并创建一个大小为 `n x m` 的二维字符矩阵。然后,我们按行读取矩阵的数据,并调用 `maximalSquare` 函数进行求解。最后,输出最大正方形边长。 在动态规划的解法中,我们使用一个二维数组 `dp` 来记录以当前位置为右下角的最大正方形边长。遍历矩阵中的每个元素,如果当前元素为 '1',则根据其左方、上方和左上方的最大正方形边长计算出当前位置的最大正方形边长,并更新 `dp` 数组和最大边长变量。 请注意,以上代码仅为示例,可能需要根据具体题目要求进行适当修改。同时,为了简化示例,未进行输入验证,请确保输入的矩阵符合题目要求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BIGBIGPPT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值