Em...属于一知道就会,不知道的话比较难想。
我们先看题:
我们不妨把1抽象成一个平面上的点,因此可以变成这一幅图:
我们假设每一个点被向上牵拉了一根线:
显然,每一条悬线都有可能成为边界限制,我们确定一条悬线,乘上悬线最左可到的+最右可到的距离即可。
首先,对于上下边界的悬线,我们记h[i][j]为(i,j)的悬线长度,易得方程:
h[i][j]=h[i-1][j]+1(a[i][j]=0)或者=0(a[i][j]=1).
我们再维护向左的长度。
我们记l[i][j]表示向左最远.l[i][j]=l[i][j-1]+1(a[i][j]=0)/0(a[i][j]=1)
我们记L[i][j]表示(i,j)这条悬线向左最远。
L[i][j]=min(L[i-1][j],l[i][j]).
向右同理。
下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
int l[100][100],r[100][100],h[100][100],n,a[90][90];
int main(){cin>>n;int ans=0;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){cin>>a[i][j];}}for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(a[i][j]==1){h[i][j]=0;l[i][j]=0;}else{h[i][j]=h[i-1][j]+1;l[i][j]=l[i][j-1]+1;}}for(int j=n;j>=1;j--){if(a[i][j]==1){r[i][j]=0;}else r[i][j]=r[i][j+1]+1;}}for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(h[i][j]>=2){//注意为2,若为1时会把上面的0带下来,而事实上1的值不用改l[i][j]=min(l[i][j],l[i-1][j]);r[i][j]=min(r[i][j],r[i-1][j]);}ans=max(ans,(r[i][j]+l[i][j]-1)*h[i][j]);}}cout<<ans;
}
那么如果要求是正方形呢?
很简单,我们只要把h[i][j]与r[i][j]+l[i][j]-1取min并平方即可。
我们来看一个变形题吧:
这里有两种方法:
1.我们还是用悬线,只不过转移条件需要修改(与自己颜色不同时转移)
2.我们先进行染色操作,我们按照国际象棋去染色,我们把国际象棋为1的位置进行颠倒。1变成0,0变成1,我们再求其中的全0/1最大子矩形即可(我们反着看,把全0/1的恢复一下不就是了吗)
下面给出法2的AC代码:
#include<bits/stdc++.h>
using namespace std;
int l[2010][2010],r[2010][2010],h[2100][2010],n,m,a[2010][2010];
int l1[2010][2010],r1[2010][2010],h1[2100][2010];
int main(){cin>>n>>m;int ans0=0,ans1=0,ans00=0,ans11=0;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){scanf("%d",&a[i][j]);}}int cnt=1;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(j%2==cnt) a[i][j]=1-a[i][j];}cnt=1-cnt;}for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(a[i][j]==1){h[i][j]=0;l[i][j]=0;}else{h[i][j]=h[i-1][j]+1;l[i][j]=l[i][j-1]+1;}}for(int j=m;j>=1;j--){if(a[i][j]==1){r[i][j]=0;}else r[i][j]=r[i][j+1]+1;}}for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(h[i][j]>=2){l[i][j]=min(l[i][j],l[i-1][j]);r[i][j]=min(r[i][j],r[i-1][j]);}ans0=max(ans0,(r[i][j]+l[i][j]-1)*h[i][j]);ans00=max(ans00,min(r[i][j]+l[i][j]-1,h[i][j])*min(r[i][j]+l[i][j]-1,h[i][j]));}}for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(a[i][j]==0){h1[i][j]=0;l1[i][j]=0;}else{h1[i][j]=h1[i-1][j]+1;l1[i][j]=l1[i][j-1]+1;}}for(int j=m;j>=1;j--){if(a[i][j]==0){r1[i][j]=0;}else r1[i][j]=r1[i][j+1]+1;}}for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(h1[i][j]>=2){l1[i][j]=min(l1[i][j],l1[i-1][j]);r1[i][j]=min(r1[i][j],r1[i-1][j]);}ans1=max(ans1,(r1[i][j]+l1[i][j]-1)*h1[i][j]);ans11=max(ans11,min(r1[i][j]+l1[i][j]-1,h1[i][j])*min(r1[i][j]+l1[i][j]-1,h1[i][j]));}}cout<<max(ans00,ans11)<<endl;cout<<max(ans0,ans1);
}