洛谷多维DP(3):P1387 最大正方形——图形DP典例

P1387 最大正方形

在这里插入图片描述

输入输出样例
输入 #1复制
4 4
0 1 1 1
1 1 1 0
0 1 1 0
1 1 0 1
输出 #1复制
2

总结目录

1.状态方程的获取
2.初始条件与计算顺序

1 状态方程获取

这题思维难度不高,关键在于如何定义dp。对于这种类似于棋盘的图形dp问题,显然属于多维dp了。但是dp[i][j]到底应该如何进行具体的定义。

一种是直接根据题目进行修改的:定义dp[i][j]为一直到[i,j]区间能够得到的最大正方形的边长。这样的话我们最后求的就是dp[m][n],但是这样子一方面全局解和局部最优解之间关系并不明确,因为局部最优解得到的最大正方形并不一定包含[i][j](即[i][j]不一定是1,最大正方形可能是一个更小的结构)

因此,这里的图形dp的定义为:以[i][j]为正方形右下角点的最大边长,这个思想其实有一点像3种遍历中的以num[i]为结尾的最大升序列/最大子列和。以后有关图形的dp问题也可以考虑从图形的某个角点出发进行定义dp[i][j]

那么很简单就能写出
if(mat[i][j]==1)//当前角点为1才有资格作为正方形右下角点
dp[i][j]=min{ dp[i-1][j],dp[i-1][j-1],dp[i][j-1] }+1;

2 初始条件与计算顺序

0行与0列记为0,表明这里无法作为正方形角点。计算顺序为从左到右,从上到下。

代码

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int mat[105][105];
int dp[105][105];//dp[i][j]定义为以[i,j]为正方形右下角(包含[i,j])的最大能够构成的正方形的边数
int main() {
	memset(mat, 0, sizeof(mat));
	memset(dp, 0, sizeof(dp));
	int m, n;
	cin >> m >> n;
	for (int i = 1; i <= m; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> mat[i][j];
		}
	}
	int res = 0;
	for (int i = 1; i <= m; i++) {
		for (int j = 1; j <= n; j++) {
			if (mat[i][j] == 1) {
				dp[i][j] = min({ dp[i - 1][j],dp[i][j - 1],dp[i - 1][j - 1] }) + 1;
			}
			res = max(res, dp[i][j]);
		}
	}
	cout << res;

	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值