hdu 1505 City Game(DP)

题意:

M*N的格子构成的城市,每一个格子上不是F就是R,F代表Free,表示这个格子可以使用,R代表不可以使用。

要求:在这里面找到一个矩形,使得面积是最大的。(即必须满足覆盖矩形的每一个格子都是F)

输入:

M,N<=1000

思路:

刚开始一个思路是如果是F设成1,如果是R设成-INF。然后求最大子矩阵(最大子段和的扩展)

可是最大子矩阵的算法貌似是O(N^3)的,所以不行,,

换个思路,假设现在有一个面积,它是最大的,它有特点:向左没法延伸,向右没法延伸,向上没办法,向下也没法办。

我们不考虑向下,枚举每一层假设其这个面积的底。然后,,,然后,,这不就是柱状图求最大面积那道题了么,,那道题时间复杂度应该是介于O(n)和O(n^2)的,

俺把其看成O(C*n) C是常数,,,

看代码,,。

代码:

int m,n;
int a[1005][1005];
int leftt[1005], rightt[1005];

int proc(int x){ // row x
    rep(i,1,n) leftt[i]=rightt[i]=i;

    rep(i,2,n){
        if(a[x][i]<=a[x][i-1]){
            leftt[i] = leftt[i-1];
            while(leftt[i]-1 >0 && a[x][i]<=a[x][leftt[i]-1]){
                leftt[i] = leftt[leftt[i]-1];
            }
        }
    }

    rep2(i,n-1,1){
        if(a[x][i]<=a[x][i+1]){
            rightt[i] = rightt[i+1];
            while(rightt[i]+1<=n && a[x][i]<=a[x][rightt[i]+1]){
                rightt[i] = rightt[rightt[i]+1];
            }
        }
    }

    int ans = 0;
    rep(i,1,n){
        ans = max( ans,(rightt[i]-leftt[i]+1)*a[x][i] );
    }
    return ans;

}

int main(){

    int T;
    cin>>T;
    while(T--){
        scanf("%d%d",&m,&n);
        rep(i,1,m) rep(j,1,n){
            char kind[3];
            scanf("%s",&kind);
            if(kind[0]=='R') a[i][j]=0; else a[i][j]=1;
        }
        rep(i,2,m) rep(j,1,n){
            if(a[i][j]==0) continue;
            if(a[i-1][j]>0) a[i][j] += a[i-1][j];
        }

        int ans = 0;
        rep(i,1,m){
            ans = max( ans,3*proc(i) );
        }

        printf("%d
",ans);
    }

    return 0;
}
原文地址:https://www.cnblogs.com/fish7/p/4230017.html