求最大子矩阵悬线法(codevs 1159 最大全0子矩阵)

题目描述  Description

在一个0,1方阵中找出其中最大的全0子矩阵,所谓最大是指O的个数最多。

输入描述  Input Description

输入文件第一行为整数N,其中1<=N<=2000,为方阵的大小,紧接着N行每行均有N个0或1,相邻两数间严格用一个空格隔开。

输出描述  Output Description

输出文件仅一行包含一个整数表示要求的最大的全零子矩阵中零的个数。

样例输入  Sample Input

5
0 1 0 1 0
0 0 0 0 0
0 0 0 0 1
1 0 0 0 0
0 1 0 0 0

样例输出  Sample Output

9

本题采用悬线法,非常好的一道模板题,如果大家不知道悬线法怎么写的话:传送门

 1 #include<bits/stdc++.h>
 2 #define maxn 2999
 3 using namespace std;
 4 
 5 int h[maxn][maxn],r[maxn][maxn],l[maxn][maxn];
 6 int n;
 7 int maxr,maxl;
 8 int Map[maxn][maxn];
 9 int ans;
10 
11 int main()
12 {
13     cin>>n;
14     for(int i=1;i<=n;i++)
15       for(int j=1;j<=n;j++)
16         cin>>Map[i][j];
17     for(int i=1;i<=n;i++)
18        r[0][i]=n;
19     for(int i=1;i<=n;i++)
20     {
21        maxr=n,maxl=1;
22        for(int j=1;j<=n;j++)
23        {
24             if(Map[i][j])
25             {
26                maxl=j+1;
27                h[i][j]=l[i][j]=0;
28             }
29             else
30             {
31               h[i][j]=h[i-1][j]+1;
32               l[i][j]=max(maxl,l[i-1][j]);
33             }
34        }
35        for(int j=n;j>=1;j--)
36        {
37          if(Map[i][j])
38          {
39            maxr=j-1;
40            r[i][j]=n;
41          }
42          else
43          {
44             r[i][j]=min(r[i-1][j],maxr);
45             ans=max(ans,(r[i][j]-l[i][j]+1)*h[i][j]);
46          }
47        }
48     }
49     cout<<ans<<endl;
50    return 0;
51 }

 还可以降维,学习背包问题中的滚动数组的思想~

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

int h[maxn],r[maxn],l[maxn];
int n;
int maxr,maxl;
int Map[maxn][maxn];
int ans;

int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	  for(int j=1;j<=n;j++)
	    cin>>Map[i][j];
	for(int i=1;i<=n;i++)
	   r[i]=n;
	for(int i=1;i<=n;i++)
	{
	   maxr=n,maxl=1;
	   for(int j=1;j<=n;j++)
	   {
		    if(Map[i][j])
		    {
			   maxl=j+1;
			   h[j]=l[j]=0;
			}
			else
			{
			  h[j]++;
			  l[j]=max(maxl,l[j]);
			}
	   }
	   for(int j=n;j>=1;j--)
	   {
	     if(Map[i][j])
	     {
		   maxr=j-1;
		   r[j]=n;
		 }
		 else
		 {
		    r[j]=min(r[j],maxr);
		    ans=max(ans,(r[j]-l[j]+1)*h[j]);
		 }
	   }
	}
	cout<<ans<<endl;
   return 0;
}

  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值