其他分享
首页 > 其他分享> > 【pk赛】菜地

【pk赛】菜地

作者:互联网

题目

给你一块nxm的菜地,菜地的内容只由0和1组成
求最大的一块全为1的矩形子菜地
n,m<=1000

思路

首先可以预处理出每一行/每一块矩阵内1的个数

  1. 暴力枚举每一个矩阵的左上角、右下角
    时间复杂度\(O(n^2m^2)\)

  2. 枚举矩阵的起始两列位置,再用类似求最大子段和的思想dp

        int ans=-1e9;
	for(int l=1;l<=m;l++){
		for(int r=l;r<=m;r++){
			int tem=0,las=-1;
			for(int i=1;i<=n;i++){
				int cnt=pre[i][r]-pre[i][l-1];
				if(cnt==r-l+1){
					if(las==i-1){
						tem+=cnt;
					}
					else tem=cnt;
					las=i;
				}
				else{
					las=-1;
					tem=0;
				}
				if(tem>ans) ans=tem;
			}
		}
	}
	printf("%d\n",ans);

时间复杂度\(O(m^2n)\)
然而在这个数据范围下还是tle了

  1. 先预处理每个格子网上最多有多少个1,然后枚举每一个格子,求以它为基准的这一行的最大面积。
    和单调栈例题——求矩阵最大面积题意一样
#include<bits/stdc++.h>    
#define ll long long      
using namespace std;
const int N = 1005;
int n,m;
char a[1005][1005];
int h[N][N];
int r[N],l[N];

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>a[i][j];
		}
	}
	for(int j=1;j<=m;j++){
		for(int i=1;i<=n;i++){
			if(a[i][j]=='0') h[i][j]=0;
			else h[i][j]=h[i-1][j]+1;
		}
	}
	int ans=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			l[j]=j;
			r[j]=j;
		}
		h[i][0]=-1;
		h[i][m+1]=-1;
		for(int j=1;j<=m;j++){
			while(h[i][j]<=h[i][l[j]-1]){
				l[j]=l[l[j]-1];
			}
		}
		for(int j=m;j>=1;j--){
			while(h[i][j]<=h[i][r[j]+1]){
				r[j]=r[r[j]+1];
			}
		}
		for(int j=1;j<=m;j++){
			ans=max(ans,(r[j]-l[j]+1)*h[i][j]);
		}
	}
	cout<<ans<<endl;
	return 0;
}

标签:菜地,int,矩阵,枚举,ans,pk,1005
来源: https://www.cnblogs.com/re0acm/p/16296751.html