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);
}