假·P1736题解

为什么说是假题解呢?就是因为这篇题解提交入口已经关闭了,这就相当于是我的一个做题心得吧

这题还是很巧妙的

不过看着 \(01\) 矩阵第一反应应该是二维前缀和吧

然后还有对角线,那就单独在弄两个前缀和

于是朴素算法写好了

#include<bits/stdc++.h>
using namespace std;
int n,m,s[2510][2510],s1[2510][2510],s2[2510][2510],x;
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	  for(int j=1;j<=m;j++)
	    scanf("%d",&x),s[i][j]=s[i-1][j]+s[i][j-1]+x-s[i-1][j-1],s1[i][j]=s1[i-1][j-1]+x,s2[i][j]=s2[i-1][j+1]+x;
	for(int i=min(n,min(m,s[n][m]));i>=1;i--)
	  for(int j=i;j<=n;j++)
		for(int k=i;k<=m;k++)
		{
			int t=s[j][k]-s[j-i][k]-s[j][k-i]+s[j-i][k-i];
			if(t!=i) continue;
			if(s1[j][k]-s1[j-i][k-i]==i||s2[j][k-i+1]-s2[j-i][k+1]==i) {cout<<i<<endl;return 0;}
		}
	cout<<0;
	return 0;
}

但是很可惜,这会超时TLE记录

于是考虑加一些 \(break\)

考虑从左上角或右上角开始枚举边长,如果边长小时已不满足条件就 \(break\)

实际上就是把上面那个代码 \(i\) 循环内移

得到了以下代码

#include<bits/stdc++.h>
using namespace std;
int n,m,s[2510][2510],s1[2510][2510],s2[2510][2510],x,mx=1;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x*f;
}
int main()
{
	n=read();m=read();
	for(register int i=1;i<=n;i++)
	  for(register int j=1;j<=m;j++)
	    x=read(),s[i][j]=s[i-1][j]+s[i][j-1]+x-s[i-1][j-1],s1[i][j]=s1[i-1][j-1]+x,s2[i][j]=s2[i-1][j+1]+x;
	if(s[n][m]==0) {cout<<0;return 0;}
	for(register int j=2;j<=n;j++)
	  for(register int k=2;k<=m;k++)
	    for(register int i=2;i<=min(j,k);i++)
		{
			int t=s[j][k]-s[j-i][k]-s[j][k-i]+s[j-i][k-i];
			if(t!=i) break;
			if(s1[j][k]-s1[j-i][k-i]==i) mx=max(mx,i);
			if(mx==min(n,m)) {cout<<i;return 0;}
		}
	for(register int j=2;j<=n;j++)
	  for(register int k=1;k<=m-1;k++)
	    for(register int i=2;i<=min(j,m-k+1);i++)
		{
			int t=s[j][k+i-1]-s[j-i][k+i-1]-s[j][k-1]+s[j-i][k-1];
			if(t!=i) break;
			if(s2[j][k]-s2[j-i][k+i]==i) mx=max(mx,i);
			if(mx==min(n,m)) {cout<<i;return 0;}
		}
	cout<<mx;
	return 0;
}

于是就过了

话说还拿了第三优/jy

upd on 2022.6.11 变成第四优了/jy

posted @ 2025-05-03 08:35  zhjzhmh  阅读(3)  评论(0)    收藏  举报