前缀和zzuoj10445 魔法花园

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前缀和zzuoj10445 魔法花园相关的知识,希望对你有一定的参考价值。


 身为魔法少女的一员,学姐(头还在哦)在最后一战之后便退隐了。她决定用她剩余的魔法去圈一块矩形花园。但是有一些土地会使学姐的魔法失效(即边不可以跨越这些土地)。现在学姐想知道在这块N*M的土地上她可以获得的最大花园面积。(单位格面积为1).在这块N*M的图中,.表示学姐可以施法,X表示会失效。(1<=N,M<=200)


 技术分享

Input

输入为多组样例,第一行为N和M,下面N*M描述这个土地。

Output

输出多行,每行为麻美学姐可以获得的最大花园面积。

Sample Input

5 6 ...... ..X..X X..X.. ...... ..X... 

Sample Output

16 

HINT

 如上样例,假设麻美学姐的魔法为F,那么她圈地的方式是


.FFFF.

.FX.FX

XF.XF.

.FFFF.

..X...

 思路:

先把数据转换成01矩阵,然后维护每一行的前缀和。接下来就可以用O(1)的时间复杂度查询一段数组的和。若一段数组的和为0,则没有X,否则就有X。

枚举矩形的左右两列,然后开始搜索矩形的上下两行。在行向下滑动的过程用一个值维护矩形的上边的行号。若找到一个全0行,先判断是否已经存在一个合法的矩形的上边,若不存在则用该全0行的行号更新上边的行号,若存在上边,则该行为矩形的下边,这时就得到了一个合法的矩形,计算面积后去更新最大面积的值。 

#include<stdio.h>

#define NOT_EXIST -1
int map[204][204];
void initial_matrix(int n,int m){
        getchar();
        for(int i=0;i<n;++i){
            for(int j=0;j<m;++j){
                if(getchar()==.) map[i][j]=0;
                else map[i][j]=1;
                if(j>0) map[i][j]+=map[i][j-1];
            }
            getchar();
        }
    //    for(int i=0;i<n;++i){
//            for(int j=0;j<m;++j){
//                printf("%d",map[i][j]);
//            }
//            printf("\n");
//        }
}
inline bool zero_point(int row,int col){
    if(col-1<0&&(map[row][col]==0)) return true;
    else if(col-1>=0&&(map[row][col]-map[row][col-1]==0)) return true;
    else return false;
}
inline bool blank_line(int row,int col_left,int col_right){
    if(col_left-1<0&&(map[row][col_right]==0)) return true;
    else if(col_left-1>=0&&(map[row][col_right]-map[row][col_left-1]==0)) return true;
    else return false;
}
void open(){
    freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout); 
}

int main(int argc,char **argv){
    int n,m;
//    open();
    while(scanf("%d%d",&n,&m)!=EOF){
        initial_matrix(n,m);
        int rectangle_top_edge;
        int max_area=0;
        for(int col_left=0;col_left<m;++col_left){
                for(int col_right=col_left; col_right < m; ++col_right){
                        rectangle_top_edge=NOT_EXIST;
                        for(int row=0;row < n; ++row){
                    //        printf("row=%d col_left%d:%d col_right%d:%d\n",row,col_left,zero_point(row,col_left),col_right,zero_point(row,col_right));
                            if(zero_point(row,col_left) && zero_point(row,col_right)){
                                if(blank_line(row,col_left,col_right)){
                                    if(rectangle_top_edge==NOT_EXIST){
                                        rectangle_top_edge=row;
                                        if(col_right-col_left+1 > max_area) {
                                            max_area=col_right-col_left+1
                        //                    printf("rectangle_top_edge=%d row=%d col_left=%d col_right=%d max_area=%d\n",rectangle_top_edge,row,col_left,col_right,max_area);                                        
                                        }
                                    }else {
                                        if((row-rectangle_top_edge+1)*(col_right-col_left+1)>max_area){
                                            max_area= (row-rectangle_top_edge+1)*(col_right-col_left+1);
                        //                    printf("rectangle_top_edge=%d row=%d col_left=%d col_right=%d max_area=%d\n",rectangle_top_edge,row,col_left,col_right,max_area);
                                        }
                                    }
                                }
                            }else{
                                rectangle_top_edge=NOT_EXIST;
                            }
                        }
                }
        }
        printf("%d\n",max_area);
    }
    return 0;
}

 

 

 

以上是关于前缀和zzuoj10445 魔法花园的主要内容,如果未能解决你的问题,请参考以下文章

前缀和乱搞 uoj 267 魔法小程序

ZZUOJ 10507: 非完美数

zzuoj 找最佳通路

ZZUOJ 10508 树状数组

zzuoj 10492

ZZUOJ 10510: 石子合并