求最大子矩阵悬线法(codevs 1159 最大全0子矩阵)
来源:互联网 发布:阿里大数据查询 编辑:程序博客网 时间:2024/05/24 04:50
题目描述 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 else30 {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 else43 {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 2999using 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;}