首页 > 代码库 > 1057: [ZJOI2007]棋盘制作

1057: [ZJOI2007]棋盘制作

 

1057: [ZJOI2007]棋盘制作

Time Limit: 20 Sec  Memory Limit: 162 MB
Submit: 2398  Solved: 1191
[Submit][Status][Discuss]

Description

 

  国际象棋是世界上最古老的博弈游戏之一,和中国的围棋、象棋以及日本的将棋同享盛名。据说国际象棋起源
于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳。而我们的主人公小Q,
正是国际象棋的狂热爱好者。作为一个顶尖高手,他已不满足于普通的棋盘与规则,于是他跟他的好朋友小W决定
将棋盘扩大以适应他们的新规则。小Q找到了一张由N*M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种
颜色之一。小Q想在这种纸中裁减一部分作为新棋盘,当然,他希望这个棋盘尽可能的大。不过小Q还没有决定是找
一个正方形的棋盘还是一个矩形的棋盘(当然,不管哪种,棋盘必须都黑白相间,即相邻的格子不同色),所以他
希望可以找到最大的正方形棋盘面积和最大的矩形棋盘面积,从而决定哪个更好一些。于是小Q找到了即将参加全
国信息学竞赛的你,你能帮助他么?

Input

  第一行包含两个整数N和M,分别表示矩形纸片的长和宽。接下来的N行包含一个N * M的01矩阵,表示这张矩形
纸片的颜色(0表示白色,1表示黑色)。

Output

  包含两行,每行包含一个整数。第一行为可以找到的最大正方形棋盘的面积,第二行为可以找到的最大矩形棋
盘的面积(注意正方形和矩形是可以相交或者包含的)。

Sample Input

3 3
1 0 1
0 1 0
1 0 0

Sample Output

4
6

HINT

 

N, M ≤ 2000

思路:单调栈;

只要将(i+j)%2==0,的方格反转下,就转变为求最大子矩阵的问题,用单调栈维护下就行,复杂度(n*m);

  1 #include<stdio.h>  2 #include<algorithm>  3 #include<iostream>  4 #include<string.h>  5 #include<queue>  6 #include<deque>  7 #include<stack>  8 #include<math.h>  9 using namespace std; 10 int ma[3000][3000]; 11 int a[3000][3000]; 12 int b[3000][3000]; 13 stack<int>stac; 14 int R[3000]; 15 int L[3000]; 16 int main(void) 17 { 18     int n,m; 19     int i,j; 20     scanf("%d %d",&n,&m); 21     { 22         memset(a,0,sizeof(a)); 23         memset(b,0,sizeof(b)); 24         for(i = 1; i <= n; i++) 25         { 26             for(j = 1; j <= m; j++) 27             { 28                 scanf("%d",&ma[i][j]); 29             } 30         } 31         for(i = 1; i <= n; i++) 32         { 33             for(j = 1; j <= m; j++) 34             { 35                 if((i+j)%2) 36                 { 37                     ma[i][j]+=1; 38                     ma[i][j]%=2; 39                 } 40                 //printf("%d ",ma[i][j]); 41             }//printf("\n") 42         } 43         for(i = 1; i <= n; i++) 44         { 45             for(j = 1; j <= m; j++) 46             { 47                 if(ma[i][j]) 48                 { 49                     a[i][j] = a[i][j-1]+1; 50                 } 51                 if(!ma[i][j]) 52                 { 53                     b[i][j] = b[i][j-1]+1; 54                 } 55             } 56         } 57         int maxx = 0; 58         int maxxx = 0; 59         for(j = 1; j <= m; j++) 60         { 61             while(!stac.empty()) 62             { 63                 stac.pop(); 64             } 65             for(i = 1; i <= n; i++) 66             { 67                 if(stac.empty()) 68                 { 69                     L[i] = 1; 70                     stac.push(i); 71                 } 72                 else 73                 { 74                     while(!stac.empty()) 75                     { 76                         int x = stac.top(); 77                         if(a[i][j] < a[x][j]) 78                         { 79                             R[x] = i-1; 80                             stac.pop(); 81                         } 82                         else break; 83                     } 84                     if(stac.empty()) 85                     { 86                         L[i] = 1; 87                         stac.push(i); 88                     } 89                     else 90                     { 91                         L[i] = stac.top()+1; 92                         stac.push(i); 93                     } 94                 } 95             } 96             while(!stac.empty()) 97             { 98                 int x= stac.top(); 99                 stac.pop();100                 R[x] = n;101             }102             for(i = 1; i <= n; i++)103             {104                 maxx = max(maxx,(R[i]-L[i]+1)*a[i][j]);105                 maxxx = max(maxxx,min((R[i]-L[i]+1),a[i][j])*min((R[i]-L[i]+1),a[i][j]));106             }107         }108         for(j = 1; j <= m; j++)109         {110             while(!stac.empty())111             {112                 stac.pop();113             }114             for(i = 1; i <= n; i++)115             {116                 if(stac.empty())117                 {118                     L[i] = 1;119                     stac.push(i);120                 }121                 else122                 {123                     while(!stac.empty())124                     {125                         int x = stac.top();126                         if(b[i][j] <= b[x][j])127                         {128                             R[x] = i-1;129                             stac.pop();130                         }131                         else break;132                     }133                     if(stac.empty())134                     {135                         L[i] = 1;136                         stac.push(i);137                     }138                     else139                     {140                         L[i] = stac.top()+1;141                         stac.push(i);142                     }143                 }144             }145             while(!stac.empty())146             {147                 int x= stac.top();148                 stac.pop();149                 R[x] = n;150             }151             for(i = 1; i <= n; i++)152             {153                 maxx = max(maxx,(R[i]-L[i]+1)*b[i][j]);154                 maxxx = max(maxxx,min((R[i]-L[i]+1),b[i][j])*min((R[i]-L[i]+1),b[i][j]));155             }156         }157         printf("%d\n",maxxx);158         printf("%d\n",maxx);159     }160     return 0;161 }

 

 

1057: [ZJOI2007]棋盘制作