最大子矩阵——枚举就能满分的Bug

最大子矩阵
【题目描述】
已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是1×1)子矩阵。

比如,如下4×4的矩阵

0 -2 -7 0

9 2 -6 2

-4 1 -4 1

-1 8 0 -2
的最大子矩阵是

9 2

-4 1

-1 8
这个子矩阵的大小是15。

【输入】
输入是一个N×N的矩阵。输入的第一行给出N(0<N≤100)。再后面的若干行中,依次(首先从左到右给出第一行的N个整数,再从左到右给出第二行的N个整数……)给出矩阵中的N2个整数,整数之间由空白字符分隔(空格或者空行)。已知矩阵中整数的范围都在[−127,127]。

【输出】
输出最大子矩阵的大小。

【输入样例】
4
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
【输出样例】
15
【来源】
一本通在线评测
咳咳!各位,都来看一下这道题!
第一反应应该都是动态规划吧。
但是!容我再看一下数据!N(0<N≤100)也就是说,枚举只要不超过四层(100^4=100000000),就绝对不会超时。同理,枚举在理论上是可以拿到满分的!
但怎么拿呢?
首先
纯枚举的话,先枚举这个矩阵的头的坐标(t1,t2),再枚举矩阵尾的两个坐标,再累加这个矩阵的数字。将每个矩阵都枚举到。

for(int t1=1;t1<=n;t1++)
	{
		for(int t2=1;t2<=n;t2++)
		{
			for(int w1=1;w1<=n;w1++)
			{
				for(int w2=1;w2<=n;w2++)
				{
					for(int i=t1;i<=w1;i++)
					{
						for(int j=t2;j<=w2;j++)
						{
							sum[k]+=a[i][j];
						}
					} 
					maxn=max(maxn,sum[k]);
					k++;
				}
			}
		}
	}

But! 这是一个2+2+2的六重循环!部分分是可以拿到的,但满分绝对会TIE的!难道枚举终究拿不到满分吗?必须要启用动态规划吗?
等等!
前缀和,助我一臂之力!
前缀和,就是用许多和值加减,得到一些其他和值,这样就不用枚举每一个矩阵了!
嗯,可能说的有点抽象。不明白的话,看一下这个图。
在这里插入图片描述

这样的话求前缀和只需要枚举所有尾的坐标,就是一个四重循环。在通过前缀和求值时,也只需要四重循环了。

for(int w1=1;w1<=n;w1++)
		{
			for(int w2=1;w2<=n;w2++)
			{
				for(int i=1;i<=w1;i++)
				{
					for(int j=1;j<=w2;j++{
						sum[w1][w2]+=a[i][j];
					}
				}
				for(int k=1;k<w1;k++)
				{
					for(int h=1;h<w2;h++)
					{
						maxn=max(maxn,sum[w1][w2]);//别忘了比较时也要比前缀和。
						maxn=max(maxn,sum[w1][w2]-sum[w1][h]-sum[k][w2]+sum[k][h]);
						maxn=max(maxn,sum[w1][w2]-sum[w1][h]);
						maxn=max(maxn,sum[w1][w2]-sum[k][w2]);
					}
				}
				
			}
	}

OK,满分,但是,不够beautiful!找前缀和时其实还可以再优化一下。
在这里插入图片描述

for(int w1=1;w1<=n;w1++)
		{
			for(int w2=1;w2<=n;w2++)
			{
				sum[w1][w2]=sum[w1-1][w2]+sum[w1][w2-1]-sum[w1-1][w2-1]+a[w1][w2];
				for(int k=1;k<w1;k++)
				{
					for(int h=1;h<w2;h++)
					{
						maxn=max(maxn,sum[w1][w2]);
						maxn=max(maxn,sum[w1][w2]-sum[w1][h]-sum[k][w2]+sum[k][h]);
						maxn=max(maxn,sum[w1][w2]-sum[w1][h]);
						maxn=max(maxn,sum[w1][w2]-sum[k][w2]);
					}
				}
				
			}
	}

加上输入输出,完美!

#include<bits/stdc++.h>
using namespace std;
int a[1010][1000],m,n,maxn=-100000000,sum[1000][1000];
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++) 
		{
			cin>>a[i][j];
		}
	} 
	for(int w1=1;w1<=n;w1++)
		{
			for(int w2=1;w2<=n;w2++)
			{
				sum[w1][w2]=sum[w1-1][w2]+sum[w1][w2-1]-sum[w1-1][w2-1]+a[w1][w2];
				for(int k=1;k<w1;k++)
				{
					for(int h=1;h<w2;h++)
					{
						maxn=max(maxn,sum[w1][w2]);
						maxn=max(maxn,sum[w1][w2]-sum[w1][h]-sum[k][w2]+sum[k][h]);
						maxn=max(maxn,sum[w1][w2]-sum[w1][h]);
						maxn=max(maxn,sum[w1][w2]-sum[k][w2]);
					}
				}
				
			}
	}
	cout<<maxn;
    return 0;
}


在这里插入图片描述

下线!散会!各回各家!

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
最大矩阵问题是一个经典的算法问题,可以通过贪心算法来解决。贪心算法的基本思想是每一步都做出局部最优的选择,以求得全局最优解。 在解决最大矩阵问题时,可以利用动态规划的思想。我们可以定义一个辅助矩阵dp,其中dp[i][j表示以矩阵中第i行第j列元素为右下角的矩阵最大大小。然后,我们可以通过以下递推关系来计算dp矩阵的每个元素: dp[i][j = matrix[i][j + dp[i-1][j + dp[i][j-1 - dp[i-1][j-1] 其中,matrix[i][j表示原始矩阵中第i行第j列的元素。 然后,我们可以遍历dp矩阵的每个元素,找到其中的最大值,即为最大矩阵的大小。 对于给定的例,我们可以得到以下dp矩阵: 0 -2 -9 -9 9 11 1 0 5 -1 -2 -1 4 3 5 6 其中,最大矩阵的大小为15,对应的矩阵为: 9 2 -4 1 -1 8 因此,最大矩阵的大小为15。 可以看出,通过利用贪心算法和动态规划的思想,我们可以高效地解决最大矩阵问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [最大矩阵(贪心算法)](https://blog.csdn.net/Annconda/article/details/127173365)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [贪心算法——1224:最大矩阵](https://blog.csdn.net/qq_45700119/article/details/122025478)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [最大矩阵——贪心算法](https://blog.csdn.net/FENGXUEYINCHEN/article/details/111940408)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值