steven张 @ 2018-01-10 10:01:04
思路很简单,求出前缀和sum,dp【0】【i】【j】是代表a【i】【j】这个点是对角线上的点,并且方向是从左上到右下的对角线的长度,dp【1】【i】【j】是从左下到右上,从头扫一遍,看看左上右上分别有没有对角线,有的话,根据前缀和判断一下扩大了的正方形里面有没有1的点,没有就长度加一,同时更新最值
#include<bits/stdc++.h>
using namespace std;
const int maxn=2510;
int a[maxn][maxn],sum[maxn][maxn],dp[2][maxn][maxn];
int n,m,ans;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
if(!a[i][j])dp[0][i][j]=dp[1][i][j]=0;
else dp[1][i][j]=dp[0][i][j]=1,ans=1;
sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j])
{
if(dp[0][i-1][j-1]!=0)
{
int t=dp[0][i-1][j-1];
if(sum[i][j-1]-sum[i-1][j-1]-sum[i][j-t-1]+sum[i-1][j-t-1]==0&&sum[i-1][j]-sum[i-t-1][j]-sum[i-1][j-1]+sum[i-t-1][j-1]==0)
dp[0][i][j]=dp[0][i-1][j-1]+1,ans=max(ans,dp[0][i][j]);
}
if(dp[1][i-1][j+1]!=0)
{
int t=dp[1][i-1][j+1];
if(sum[i][j+t]-sum[i][j]-sum[i-1][j+t]+sum[i-1][j]==0&&sum[i-1][j]-sum[i-t-1][j]-sum[i-1][j-1]+sum[i-t-1][j-1]==0)
dp[1][i][j]=dp[1][i-1][j+1]+1,ans=max(ans,dp[1][i][j]);
}
}
}
}
printf("%d",ans);
return 0;
}
/* */
by 斯茂 @ 2018-03-04 21:22:56
我教你一个办法,把第四个点数据下载下来,加一条判断,如果是第四个点的输入,就对应第四个点的输出,相当于作弊的方法,这样能过,但如果你想找到自己哪里错了,就好好读你的代码吧
by thu_changge @ 2018-03-21 21:23:53
这种方法不可取,数据只是让你分析的,你下载下来更方便测试,而不是用来作弊的
by 夏夕secret @ 2018-04-04 17:25:43
同样错第四个点,不知所措