矩阵大师(Matrix Swapping II)题解

ZZUOJ上的一道题目,原题应该是Matrix Swapping II,两道题的区别只是少了一个无关紧要的变量输入。
题目链接:矩阵大师

矩阵大师

题目描述:
给一个01矩阵,现在你可以交换任意列,交换任意次,问:
交换后的矩阵中出现的全1矩阵,面积最大是多大
01矩阵(只有 0 ,1 的矩阵 ):
00000
11111
00000
形如上面的矩阵 就是01矩阵 ,上面这个矩阵的最大全1矩形 面积为5

输入:
第一行一个T,代表有T组测试数据
每组数据第一行两个整数 n,m (n<=2000,m<=2000),代表矩阵的大小。
接下来n行,每行一个字符串,字符串大小为m,代表着01矩阵
保证 n*m的总和不超过2000000

输出:
T行,输出最大全1矩阵面积

分析

题目的做法类似于动态规划,但不同的是划分的各个子问题间并没有‘无后效性’,答案是从所有子问题中取最大值。可以按照如下思路:
①若矩阵只有一行,如何求最大面积?由于列的顺序可以随意改变,那么将所有值为1的列连在一起,就得到了答案
②若矩阵有两行,如何求最大面积?首先,我们分析两种情况。
这个最大矩阵中只有第一行的元素,而没有第二行的元素,这个情况就可以直接看作问题①了,因为只需要查看第一行的元素组成的最大矩阵,就能知道答案。
这个最大矩阵同时包含了两行的元素。既然它必然包含第二行的元素,那么我们就将所有第二行为1的列先拼在一起,因为这样使得最大矩阵在第二行的可能宽度达到最大,这里使用了贪心算法的思想;之后,我们按照每一列第二行元素[与其相连的上方的1]的数量,对其降序排列,因为这样使得最大矩阵在第一行的可能宽度也达到最大。此时,设i=1,并遍历到m,代表最大矩阵中的元素跨越了第1列到第i列,即矩阵宽度为i,易知矩阵长度为[与第二行元素相连的上方的1]的数量,两者相乘即获得面积。遍历完成后,取得到的所有面积的最大值,就是答案。
③若矩阵有n行,如何求最大面积?显然,只要将②的情况推广即可。
完成题目的重点只有两个:获得每个元素与其相连的上方的1的数量;对每一行进行遍历时,根据这个数量进行排序求面积。

代码里用%d读了数据,其实直接用%s读更方便,不过一些地方需要做细小的变更

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define max(a,b) a>b?a:b
#define zo(a)	a=='1'?1:0


int main()
{
	int n,m,time;
	static int dp[2020][2020],s[2020];
	scanf("%d",&time);
	while(time--)
	{
		scanf("%d%d",&n,&m);
		int ans=0;
		for(int i=1;i<=n;i++)
		{
			getchar();
			for (int j=1;j<=m;j++)
			{
				dp[i][j]=zo(getchar());
				if (dp[i][j]==1)
					dp[i][j]=dp[i-1][j]+1;
				s[j]=dp[i][j];
			}
			std::sort(s+1,s+m+1);
			for (int j=1;j<=m;j++)
			{
				ans=max(ans,s[j]*(m-j+1));
			}
				
		}
		printf("%d\n",ans);
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值