情形如下:
已知在如下二维平面mxn内,存在障碍物‘X’,为了避开障碍物请计算最大的矩阵面积。
XXOOXO
OOXXOO
XOOOXO
XOOXOX
OOOXOO
由于数据量小,显然可得出最大的矩阵面积区域
XXOOXO
OOXXOO
XOOOXO
XOOXOX
OOOXOO
故,ans=6
那么,如何用程序求最大矩阵面积?
方法一:动态规划O(m*n)
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #define N 5000 #define left Left #define right Right using namespace std; /*二维平面mxn内的最大矩阵面积*/ int up[N][N],left[N][N],right[N][N]; int maxMatrixArea(string str[],int m,int n){ memset(up,0,sizeof(up)); memset(left,0,sizeof(left)); memset(right,0,sizeof(right)); int ans = -1; for(int i=0;i<m;i++){ int lo=-1,ro=n; //from left to right for(int j=0;j<n;j++){ //\'X\' if(str[i][j]==\'X\'){ up[i][j]=0; left[i][j]=0; lo=j; } else{ up[i][j]=(i==0?1:up[i-1][j]+1); left[i][j]=(i==0?lo+1:max(lo+1,left[i-1][j])); } } //from right to left for(int j=n-1;j>=0;j--){ if(str[i][j]==\'X\'){ right[i][j]=n; ro=j; }else{ right[i][j] = (i==0?ro-1:min(ro-1,right[i-1][j])); ans = max(ans,up[i][j]*(right[i][j]-left[i][j]+1)); } } //cout<<"Get ans while i="<<i<<":"<<ans<<endl; } return ans; } string str[N]; int main(){ int m,n,**mat; freopen("datain.txt","r",stdin); while(cin>>m>>n){ for(int i=0;i<m;i++){ cin>>str[i]; cout<<str[i]<<endl; } int ans = maxMatrixArea(str,m,n); cout<<ans<<endl; } return 0; }
注:
红色代码部分需注意!
方法二:二维转换01后枚举边界(m*m*n)
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #define N 5000 using namespace std; /*二维平面mxn内的最大矩阵面积,转化为0,1之后求二维最大矩阵和*/ int arr[N][N]; int T[N],s[N]; //T[],s[]为辅助数组 int maxPartOfArray(int *A,int n){ s[0]=0; for(int i=0;i<n;i++){ s[i+1]=s[i]+A[i]; } int ans = s[0],minSi=s[0]; for(int i=0;i<=n;i++){ ans = max(ans,s[i]-minSi); minSi = min(minSi,s[i]); } return ans; } void test(){ int a[5]={2,-1,3,0,3}; cout<<maxPartOfArray(a,5)<<endl; } int maxMatrixArea(string str[],int m,int n){ int ans = 0; for(int i=0;i<=m;i++){ if(i==0){ for(int j=0;j<n;j++){arr[i][j]=0;} continue; } for(int j=0;j<n;j++){ arr[i][j]=(str[i-1][j]==\'X\')?-10000:1; } } //两层循环,枚举上下边界 for(int i=0;i<m;i++){ memset(T,0,sizeof(T)); for(int ii=i+1;ii<=m;ii++){ for(int j=0;j<n;j++){ T[j] += arr[ii][j]; } ans = max(ans,maxPartOfArray(T,n)); } } return ans; } string str[N]; int main(){ //test(); int m,n; freopen("datain.txt","r",stdin); while(cin>>m>>n){ for(int i=0;i<m;i++){ cin>>str[i]; cout<<str[i]<<endl; } int ans = maxMatrixArea(str,m,n); cout<<ans<<endl; } return 0; }
注:
- “-10000”是界定值,起到跳过障碍物的作用。
- 为了方便枚举,将mxn扩大为(m+1)xn。