对于洛谷P1387 最大正方形的基于二位前缀和的解法

————————————本文旨在讨论交流计算机知识,欢迎指正—————————————

看到此题,笔者的第一印象就是正方形和边长,之间有开方的关系。

既然题目给了1是正方形的判定指标 ,那么思路也就很简单了,如果某一块的和开方和边长相等即满足题目要求,用max(x,y)来更新边长;

如此,我们首先想到的方法即二维前缀和:

   cin>>n>>m;
    int a[n][m];
    int pre[n][m];
    for(int i=0;i<n;i++)//输入每个格子的数字
        {
            for(int j=0;j<m;j++)
                {
                    cin>>a[i][j];
                }
        }
    for(int i=0;i<n;i++)pre[i][0]=a[i][0];//初始化二位前缀和
    for(int j=0;j<m;j++)pre[0][j]=a[0][j];//同上
    for(int i=1;i<n;i++)
        {
            for(int j=1;j<m;j++)
                {
                    pre[i][j]=a[i][j]+pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1];//构造二维前缀和
                }
        }

下一步,则是边长的匹配了:

这里笔者选用枚举法,即枚举边长,如果满足则更新记录res答案,并l++,继续枚举看是否成功,如果满足则再次自增和更新记录......

上代码:

  int res=0;
    int l=1;
    for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
                {
                    if(pre[i][j]-pre[i-l][j]-pre[i][j-l]+pre[i-l][j-l]==l*l)//判断(i,j)是否可以形成l边长的正方形;(不用担心会遗漏,如果l-1满足而l不满足,前面l++的时候res已经记录了l-1可行了,就不用在试l-1行不行,这样浪费时间空间)
                    {
                        res=max(res,l);//更新res
                        l++;//继续枚举
                    }
                }
        }

最后输出res即可;

下面附上完整代码:

#include<bits/stdc++.h>
using namespace std;
int n,m;
int main()
{
    cin>>n>>m;
    int a[n][m];
    int pre[n][m];
    for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
                {
                    cin>>a[i][j];
                }
        }
    for(int i=0;i<n;i++)pre[i][0]=a[i][0];
    for(int j=0;j<m;j++)pre[0][j]=a[0][j];
    for(int i=1;i<n;i++)
        {
            for(int j=1;j<m;j++)
                {
                    pre[i][j]=a[i][j]+pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1];
                }
        }
    int res=0;
    int l=1;
    for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
                {
                    if(pre[i][j]-pre[i-l][j]-pre[i][j-l]+pre[i-l][j-l]==l*l)
                    {
                        res=max(res,l);
                        l++;
                    }
                }
        }
    cout<<res<<endl;
    return 0;
}

 

希望能对你有所帮助!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值