1057: [ZJOI2007]棋盘制作
Posted SJY
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1057: [ZJOI2007]棋盘制作相关的知识,希望对你有一定的参考价值。
1057: [ZJOI2007]棋盘制作
Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 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
1 0 1
0 1 0
1 0 0
Sample Output
4
6
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 else 122 { 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 else 139 { 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]棋盘制作的主要内容,如果未能解决你的问题,请参考以下文章