洛谷P1387最大正方形(dp,前缀和)

题目描述

在一个n*m的只包含0和1的矩阵里找出一个不包含0的最大正方形,输出边长。

输入输出格式

输入格式:

输入文件第一行为两个整数n,m(1<=n,m<=100),接下来n行,每行m个数字,用空格隔开,0或1.

输出格式:

一个整数,最大正方形的边长

输入输出样例

输入样例#1:
4 4
0 1 1 1
1 1 1 0
0 1 1 0
1 1 0 1
输出样例#1:
2

暴力A了(有技巧的暴力)
/*
二维前缀和枚举
这样的水题搞了一个多小时,原来是公式背错了......
枚举每一个子矩阵的和是否等于边长的平方 自己yy的,没想到还过了
不算慢。 
但其实是dp......又伤心了 
*/

#include<iostream>
#include<cstdio>
#define maxn 101

using namespace std;
int n,m,ans,tot,cnt;
int s[maxn][maxn],map[maxn][maxn],sum[maxn][maxn];

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
      for(int j=1;j<=m;j++)
        {
            scanf("%d",&map[i][j]);
            s[i][j]=s[i][j-1]+map[i][j];
        }
    for(int i=1;i<=n;i++)
      for(int j=1;j<=m;j++)
        sum[i][j]=sum[i-1][j]+s[i][j];
    
    for(int i=1;i<=n;i++)
      for(int j=1;j<=m;j++)
      {
          int p=i,q=j,tmp=1;
          if(map[p][q]==1 && sum[p][q]-sum[i-1][q]-sum[p][j-1]+sum[i-1][j-1]==tmp*tmp && p<=n&&q<=m)
          {
              while(map[p][q]==1 && sum[p][q]-sum[i-1][q]-sum[p][j-1]+sum[i-1][j-1]==tmp*tmp && p<=n&&q<=m) 
                  p++,q++,tmp++;
            ans=max(ans,p-i);
        }
      }
    printf("%d
",ans);
    return 0;
}

正解dp

//其实方程很好想,就是没勇气写,怕给输出0.... 

#include<iostream>
#include<cstdio>
 
using namespace std;
int a[105][105]= {{0}},f[105][105]= {{0}},n,m,maxb=1;

int minn(int a,int b,int c)
{
    return min(min(a,b),c);
}

int main()
{
    cin>>n>>m;
    for(int i=1; i<=n; i++)
      for(int j=1; j<=m; j++)
        cin>>a[i][j];
    for(int i=1; i<=n; i++)
      for(int j=1; j<=m; j++)
        {
            if(a[i][j]==0) continue;
            f[i][j]=minn(f[i-1][j],f[i][j-1],f[i-1][j-1])+1;
        }
    for(int i=1; i<=n; i++)
      for(int j=1; j<=m; j++)
        if(f[i][j]>maxb)
          maxb=f[i][j];    
    cout<<maxb;
}
折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
原文地址:https://www.cnblogs.com/L-Memory/p/6362307.html