1. 程式人生 > >HihoCoder1673 : 01間隔矩陣([Offer收割]編程練習賽41)(單調隊列)

HihoCoder1673 : 01間隔矩陣([Offer收割]編程練習賽41)(單調隊列)

sca pre code ring 得到 scanf == pri nbsp

描述

給定一個N × M的01矩陣,小Hi希望從中找到一個01間隔的子矩陣,並且子矩陣的面積越大越好。

例如對於

0101010

1000101

0101010

1010101

0101010

在右側有一個5 × 4的01間隔子矩陣,在下方有一個3 × 7的01間隔子矩陣。

輸入

第一行包含兩個整數N和M。

以下N行M列包含一個N × M的01矩陣。

對於30%的數據,1 ≤ N, M ≤ 250

對於100%的數據,1 ≤ N, M ≤ 2000

輸出

輸出最大的01間隔子矩陣的面積。

樣例輸入

5 7  
0101010
1000101
0101010
1010101
0101010

樣例輸出

21
  • 模型:滑動窗口,最大廣告牌面積
  • 手段:單調隊列
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=2010;
char c[maxn][maxn];
int H[maxn][maxn],L[maxn][maxn],R[maxn][maxn],n,m,i,j,ans=0;;
int main()
{
    scanf(
"%d%d",&n,&m); for(i=1;i<=n;i++) scanf("%s",c[i]+1); for(i=1;i<=m;i++) H[1][i]=1; //得到h for(i=1;i<=m;i++) for(j=2;j<=n;j++) H[j][i]=c[j][i]==c[j-1][i]?1:H[j-1][i]+1; for(i=1;i<=n;i++) //得到相應h的左延伸
for(j=1;j<=m;j++){ if(j==1) { L[i][j]=1;continue;}//邊界處理 int k=j; while(k>1&&c[i][k]!=c[i][k-1]&&H[i][k-1]>=H[i][j]) k=L[i][k-1]; L[i][j]=k; } for(i=1;i<=n;i++) //得到相應h的右延伸 for(j=m;j>=1;j--){ if(j==m) {R[i][j]=m;continue;} int k=j; while(k&&k<m&&c[i][k]!=c[i][k+1]&&H[i][k+1]>=H[i][j]) k=R[i][k+1]; R[i][j]=k; } for(i=1;i<=n;i++) for(j=1;j<=m;j++) if((R[i][j]-L[i][j]+1)*H[i][j]>ans) ans=(R[i][j]-L[i][j]+1)*H[i][j]; printf("%d\n",ans); return 0; }

HihoCoder1673 : 01間隔矩陣([Offer收割]編程練習賽41)(單調隊列)