列表

详情


NC207173. 求面积

描述

给你一个 n 行 m 列的 0 1 矩阵,我们将该矩阵中完全由 0 或完全由 1 组成的子矩阵叫做纯矩阵。请你回答所给矩阵的最大纯矩阵面积是多少?

输入描述

第一行包含一个整数 T ( 1 ≤ T ≤ 10 ) 表示共有T组测试样例;
接下来每组的第一行有两个整数n , m ( 1 ≤ n * m ≤ 1e6 )
n - 行数;
m - 列数;
接下来 n 行,每行包含 m 个整数 0 / 1。

输出描述

每组输出一个整数,对应所给矩阵的最大纯矩阵面积。

示例1

输入:

2
3 3
1 1 1
1 0 0
1 0 0
2 2
1 0
0 1

输出:

4
1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 1153ms, 内存消耗: 12380K, 提交时间: 2020-06-07 12:55:38

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 1000010;
struct Stack{
	int id,num;
}Stack[MAXN];
int n,m;
int test(int x[MAXN]){



	int top,i,temp,res=0;
	x[m+1] = -1;
	top = -1;
	for(i = 1;i<=m+1;i++){
		while(top>-1 && x[i]<Stack[top].num){
			temp = Stack[top].num * (i-1 - (top? Stack[top-1].id: 0));
			res = max(res,temp);
			top--;
		}
		Stack[++top].id = i;
		Stack[top].num = x[i];
	}
	return res;
}
int a[MAXN];
int dp[2][MAXN];
int gao() {
	memset(dp, 0, sizeof(dp));
	int ans = 0;
	int now = 0;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			int id = (i-1)*m + j-1;
			if (a[id]) {
				dp[now][j] = 1 + dp[now^1][j];
			} else {
				dp[now][j] = 0;
			}
		}
		ans = max(ans, test(dp[now]));
		now ^= 1;
	}
	return ans;
}

int main() {
	int T;
	scanf("%d", &T);
	while (T--) {
		scanf("%d%d", &n, &m);
		for (int i = 0; i < n*m; i++)
			scanf("%d", &a[i]);
		int ans = gao();
		for (int i = 0; i < n*m; i++)
			a[i] = a[i]^1;
		ans = max(ans, gao());
		printf("%d\n", ans);
	}

	return 0;
}

C++14(g++5.4) 解法, 执行用时: 1755ms, 内存消耗: 84552K, 提交时间: 2020-06-09 17:29:20

#include<bits/stdc++.h>
using namespace std;
const int MAX = 1e6+5; 

vector<int> a[MAX], sum[MAX];

int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		int n, m;
		scanf("%d%d",&n,&m);
		for(int i = 0;i < n;i++){
			a[i].clear();sum[i].clear();
			for(int j = 0;j < m;j++){
				int x;
				scanf("%d",&x);
				a[i].push_back(x);
				if(j==0||a[i][j-1]!=x) sum[i].push_back(1);
				else sum[i].push_back(sum[i][j-1]+1); 	
			}
		}
		int ans = 0;
		for(int i = 0;i < n;i++){
			for(int j = 0;j < m;j++){
				int wid = sum[i][j];
				for(int k = i;k < n;k++){
					if(a[i][j]==a[k][j]){
						wid = min(wid,sum[k][j]);
						ans = max(ans,wid*(k-i+1));
					}
					else break;
				}
			}
		}
		printf("%d\n",ans);
	}
	return 0;
} 

上一题