最大子矩阵

3 篇文章 0 订阅
3 篇文章 0 订阅

4.最大子矩阵
【题目描述】
给你一个 N*M 的 01 矩阵,每次你可以交换任意两列,你可以交换无限多次。你要通过
交换操作,求出最大的全 1 子矩阵的面积,所谓面积就是指包含的 1 的个数。
【输入文件】
第一行两个正整数 N 和 M。
接下来 N 行,每行包含 M 个字符’0’或’1’,描述一个矩阵。
【输出文件】
输出仅一行,为最终的最大全 1 子矩阵的面积。
【样例输入】
10 6
001010
111110
011110
111110
011110
111111
110111
110111
000101
010101
【样例输出】
21
【样例解释】
你可以通过交换,将 2,4,5 三列交换至相邻位置,行从 2-8,列为 2,4,5 三列,所以
答案为 7*3=21。
【数据规模】
对于 10%的数据,1<=M<=5;
另有 20%的数据,1<=N,M<=1024;

对于 100%的数据,1<=N<=15000,1<=M<=1500;


题解:

这题思路很神奇啊。

对于M很小的数据,我们直接M!阶乘枚举列的可能,然后套用经典的最大子矩阵的O(N*M)的算法就行了。
我们逐行考虑,对于每一行的M个位置,都可以得到它向上延伸的连续的’1’的个数,我们称之为”高度”;显然,如果我们将该行的高度从大到小排序,那么从左往右扫一遍就可以统计出以该行为底边的最大子矩阵的面积了。于是,我们就可以得到一个O(N*M*log(M))的算法了;我们对它进行优化,考虑到当行增加1以后,高度要么增加1,要么变成0,于是我们将变成0的高度放到最后就行了,用两个指针实现就可以了,时间复杂度O(N*M)


代码:

const
        maxm            =1505;
var
	s		:ansistring;
        a,b,h,p         :array[0..maxm] of longint;
        n,m,i,j         :longint;
        ans,cnt,dnt,t   :longint;
begin
        assign(input,'logs.in');reset(input);
        assign(output,'logs.out');rewrite(output);

        readln(n,m);
        ans:=0;
        for j:=1 to m do p[j]:=j;
        for i:=1 to n do
        begin
		readln(s);
                cnt:=0;
		dnt:=m+1;
                for j:=1 to m do
                if s[p[j]]='1' then
                begin
                        inc(cnt);
                        a[cnt]:=h[j]+1;
                        b[cnt]:=p[j];
                        if cnt*a[cnt]>ans then ans:=cnt*a[cnt];
                end     else
                begin
                        dec(dnt);
                        a[dnt]:=0;
                        b[dnt]:=p[j];
                end;
                move(a,h,6008);
                move(b,p,6008);
        end;
        writeln(ans);

        close(input);close(output);
end.


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值