多维DP(6):P1736 创意吃鱼法——图形DP(2)

P1736 创意吃鱼法

在这里插入图片描述

输入输出样例
输入 #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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值