[DP] 盖房子 题解

题目描述

永恒の灵魂最近得到了面积为n*m的一大块土地(高兴ING_),他想在这块土地上建造一所房子,这个房子必须是正方形的。

但是,这块土地并非十全十美,上面有很多不平坦的地方(也可以叫瑕疵)。这些瑕疵十分恶心,以至于根本不能在上面盖一砖一瓦。

他希望找到一块最大的正方形无瑕疵土地来盖房子。

不过,这并不是什么难题,永恒の灵魂在10分钟内就轻松解决了这个问题。

现在,您也来试试吧。

输入格式

输入文件第一行为两个整数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

样例输出

2

题解

刚刚拿到这一题时,貌似不大会欸,但不难发现,这道题应该用DP来做,因为可以把n*m的大矩阵分成一个个的小矩阵,然后对一个个的子问题进行求解,这就体现了坐标DP的思想;

思考问题的本质,发现最小的完好土地是2 * 2的,因此我们可以从这最小的出发,每发现一个,就给2 * 2的矩阵的某一角+1(我用的是右下角)最后累积求最大,就是我们想要的答案;

其实上面的思路,总结一下就是若一个正方形的右下角坐标为(i,j),那么这个正方形的最大边长=min(i - 1, j; i - 1, j - 1; i, j - 1)+ 自己能组成的最大边长(我将信息都存在右下角,存在其他角也可以)至于为什么要取min,可参见短板效应

代码

#include <iostream>
using namespace std;
int n, m;
int a[1005][1005];
int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			cin >> a[i][j];
		}
	}
	int ans = 0;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (a[i][j]) { //能成为合法正方形的前提是自己是合法的 
				a[i][j] += min(min(a[i - 1][j], a[i - 1][j - 1]), a[i][j - 1]);
				ans = max(ans, a[i][j]); //所有数中找最大
			}
		}
	}
	cout << ans;
	return 0;
}

后记:同机房大佬也写了这道题的题解

posted @ 2024-02-16 07:15  Peppa_Even_Pig  阅读(67)  评论(0编辑  收藏  举报