SeaSky0606

情形如下:

已知在如下二维平面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。
 
 

分类:

技术点:

相关文章: