P1736 创意吃鱼法

python七巧板绘制鱼代码_python七巧板绘制鱼代码

输入输出样例
输入 #1复制
4 6
0 1 0 1 0 0
0 0 1 0 1 0
1 1 0 0 0 1
0 1 1 0 1 0
输出 #1复制
3
说明/提示

总结目录

1.状态方程的获得
2.关于内存与MLE的注意的地方

1.状态方程的获得

这一题一眼看上去就觉得和之前的最大正方形非常类似。对于这种图形DP,这里采用二维应该是没有什么问题的,关键是dp[i][j]要如何定义。这里由于说了是对角线,因此我们容易想到会有左对角线和右对角线。我们只要分别记为dp1,dp2,然后通过枚举来进行比较,最终得出结果就可以了

这里,我们的dp1[i][j]可以定义为以[i,j]为 只有对角线有1,其他都为0正方形的右下角,计算对角线的最大值。 注意,题目中说了,必须是对角线上都有鱼! 值得注意的是,我们dp的定义是,只有对角线是1,正方形中的其他元素都为0! 因此从dp[i-1][j-1]递推到dp[i][j]的时候,我们需要考虑到 第i行和第j列的连续0的个数即可。

这里我们定义h1[i][j]为以[i,j]为坐标点,向左h1[i][j]个单位全为0(不包含[i,j]);类似的,定义v1[i][j]为以[i,j]为坐标点,向上v1[i][j]个单位全为0(不包含[i,j]). 这里h1,v1的矩阵求取我使用了类似于线性DP的方法,以h1求取为例

if(j==1)h[i][j]=0;//第一列初始化
//以下为正常求取
if mat[i][j-1]!=0 //如果左边有0,那么h1在基础上加1即可
	h1[i][j]=h1[i][j-1]+1;
else if mat[i][j-1]==0 //如果左边不为0,那么就直接置0了
	h1[i][j]=0

当然,计算h2的时候由于定义是向右的,因此列数应该从右向左计算。

因此,我们在最终确定dp1[i][j]的时候

if mat[i][j]==1
	dp1[i][j]=mint {  dp1[i-1][j-1], h1[i][j], v1[i][j] }+1
else if mat[i][j]==0
	dp1[i][j]=0

2.关于内存与MLE的注意的地方

这里定义了多个二维数组,出现了MLE(内存超出)的现象,最终使用了short 解决了该问题。实际上我觉得这种图形DP使用short应该还是很足够的,因为每个数都是0和1.

代码

#include<iostream>
#include<algorithm>
using namespace std;

short mat[2505][2505];
short horizon[2505][2505];//h[i][j]为从[i,j]开始,向左h[i][j]个单位都为0
short vertical[2505][2505];//v[i][j]为从[i,j]开始,向上v[i][j]个单位都为0
short dp1[2505][2505];//定义dp1[i][j]为:以i,j为正方形矩阵右下角,的对角线上的最大的可吃鱼数,且正方形矩阵除了对角线外不存在其他的1
short dp2[2505][2505];//定义dp1[i][j]为:以i,j为正方形矩阵左下角,的对角线上的最大的可吃鱼数,且正方形矩阵除了对角线外不存在其他的1
short h2[2505][2505];//h2[i][j]为从[i,j]开始,向右h2[i][j]个单位都为0
short v2[2505][2505];//v2[i][j]定义为从[i,j]开始,向上v2[i][j]个单位都为0,本质和vertical[2505][2505]相同


int main() {
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			cin >> mat[i][j];
		}
	}

	//计算horizon
	//初始化水平第一列都为0
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (j == 1) {
				horizon[i][j] = 0;
			}
			else if (mat[i][j-1] == 0) {
				horizon[i][j] = horizon[i][j - 1] + 1;
			}
			else if (mat[i][j - 1] != 0) {
				horizon[i][j] = 0;
			}
		}
	}

	//计算vertical
	//初始化水平第一行都为0
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (i == 1) {
				vertical[i][j] = 0;
			}
			else if (mat[i-1][j] == 0) {
				vertical[i][j] = vertical[i-1][j] + 1;
			}
			else if (mat[i-1][j] != 0) {
				vertical[i][j] = 0;
			}
		}
	}

	//计算dp1[i][j]
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (mat[i][j] == 0) {
				dp1[i][j] = 0;
			}
			else if (mat[i][j] != 0) {
				dp1[i][j] = min({ dp1[i - 1][j - 1],vertical[i][j],horizon[i][j] }) + 1;
			}
		}
	}

	//计算h2[i][j]
	for (int i = 1; i <= n; i++) {
		for (int j = m; j >= 1; j--) {
			if (j == m) {
				h2[i][j] = 0;
			}
			else if (mat[i][j + 1] == 0) {
				h2[i][j] = h2[i][j + 1] + 1;
			}
			else if (mat[i][j + 1] != 0) {
				h2[i][j] = 0;
			}
		}
	}

	//计算v2[i][j]
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (i == 1) {
				v2[i][j] = 0;
			}
			else if (mat[i - 1][j] == 0) {
				v2[i][j] = v2[i - 1][j] + 1;
			}
			else if (mat[i - 1][j] != 0) {
				v2[i][j] = 0;
			}
		}
	}

	//计算dp2[i][j]
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (mat[i][j] == 0) {
				dp2[i][j] = 0;
			}
			else if (mat[i][j] != 0) {
				dp2[i][j] = min({ dp2[i - 1][j + 1],v2[i][j],h2[i][j] }) + 1;
			}
		}
	}

	short res1 = 0;
	short res2 = 0;
	short res = 0;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			res1 = max(res1, dp1[i][j]);
			res2 = max(res2, dp2[i][j]);
			res = max(res1, res2);
		}
	}
	cout << res;

	return 0;
}