假·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