标签:最大 max problem c++ string return while 矩形 最小
https://www.luogu.org/problem/show?pid=1387
在一个n*m的只包含0和1的矩阵里找出一个不包含0的最大正方形,输出边长。 n,m<=1e2;
枚举上下边界作为边长,,dp[k]以第k列结尾的矩形的最大宽度
预处理二维前缀和 则第k列结尾要满足p[k][j]-p[k][i-1]==x 求出最大宽度后 判断是否能作为边长O(n^3)
#include <bits/stdc++.h> using namespace std; const int N=2e3+20; int a[N][N],n,m; int p[N][N];//p[k][i] 第k列 前i个之和 int dp[N];//高度为x 以第k列结尾的矩形的最大边长 int main() { while(cin>>n>>m) { for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>a[i][j]; memset(p,0,sizeof(p)); for(int k=1;k<=m;k++) for(int i=1;i<=n;i++) p[k][i]=p[k][i-1]+a[i][k]; int ans=0; for(int i=1;i<=n;i++) { for(int j=i;j<=n;j++)//固定上下边界为i,j { int x=j-i+1,mx=0; for(int k=1;k<=m;k++)//以第k列结尾高度为(j-i+1)的最大边长 { if(p[k][j]-p[k][i-1]==x) dp[k]=dp[k-1]+1,mx=max(mx,dp[k]); else dp[k]=0; } if(mx>=x) ans=max(ans,x); } } cout<<ans<<endl; } return 0; }
O(n^2) 做法
验证(i,j)能表示多大的正方形的末尾,就要验证(i-1,j)(i,j-1)(i-1,j-1)这三个点中能作为正方形末尾的最小值,然后加上一即可。
#include <iostream> #include <cstring> #include <cmath> #define min3(x,y,z) min(x,min(y,z)) using namespace std; int main() { int a[105][105],dp[105][105],n,m,ma=0,i,j; cin>>n>>m; memset(dp,0,sizeof(dp)); for(i=1;i<=n;i++) for(j=1;j<=m;j++) cin>>a[i][j]; for(i=1;i<=n;i++) for(j=1;j<=m;j++) { dp[i][j]=a[i][j]*(min3(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+1); ma=max(ma,dp[i][j]); } cout<<ma<<endl; return 0; }
标签:最大 max problem c++ string return while 矩形 最小
原文地址:http://www.cnblogs.com/HIKARI1149/p/6745066.html