logo AlgoBeat OnlineJudge
登录 注册

题解

作者: AlgoBeat 官方账号  ·  发布于 2026-06-19 17:38:31
已通过

题意简述

给定一个只包含 的矩阵,如果可以无数次交换任意两行,求一个只包含 的子矩阵且满足面积最大,最大面积是多少?

思路分析

考虑到矩形的边一定是横平竖直的,所以先尝试确定下矩形的一边。图 1 中,如使 为矩形的一边,标定为 ,来分析怎样计算交换后的最大矩形面积。

首先,在 左侧的数字中只有最右侧的连续一段的 才有可能记成以 为边的矩形的组成部分。这部分是我们计算要使用的,标定为 ,可以考虑预处理出 表示坐标 左侧连续 的个数。

接下来,我们考虑 无数次交换任意两行 这个操作,如果每两行都可以无限交换,那么这个矩阵可以随意改变行的先后顺序,也就是按照一定顺序对行排序

想到这点后,我们思考如何排序有利于矩形面积的计算。显然,当对同一列的 从小到大排序时,对于每个第 列第 行的 值,它对后面更大的 值的位置有贡献,这里 一定在 后面,因而 ,所以 一定能和 形成矩形,这个矩形中 就是矩形的宽, 就是矩形的长。很明显, 越大矩形的长越大,矩形的宽又不 变,矩形的面积就最大,于是 最优值取

总结上一段,我们对列 值从小到大排序,依次遍历行 ,矩形最大面积不断和 取最大值,即可得到答案。

上图图 1 处理后形成下图:

注意:下图中 本应不改变,但为了识别不同的行在什么位置,我手动将它改变,上文中的 与下图中 无关。

图 2 中考虑第 行时,最大矩形面积为

图 3 中考虑第 行时,最大矩形面积为

图 4 中考虑第 行时,最大矩形面积为

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;

const int NR = 5010;
char a[NR][NR];
int c[NR][NR];

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

暂无评论

登录 后即可评论。