题目描述
给出一个n×n的矩阵,矩阵中,有些格子被染成白色,有些格子被染成黑色,现要求矩阵中白色矩形的数量
输入输出格式
输入格式:
第一行,一个整数n,表示矩形的大小。
接下来n行,每行n个字符,这些字符为“W”或“B”。其中“W”表示白格,“B”表示黑格。
输出格式:
一个正整数,为白色矩形数量
输入输出样例
输入样例#1:
4 WWBW BBWB WBWW WBWB
输出样例#1:
15
因为前面在USACO里面做过好几道关于在平面内找矩阵的问题了
所以当我看到这一道题的时候就马上想到了,两条边确定矩阵的方法
首先就是枚举两列,然后搞两个指针,p2用for循环开路,p1跟在后面,然后维护一下指针,时间复杂度O(N^3)
代码
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
using namespace std;
const int N = 210 ;
int n ;
char st[N] ;
int sum[N][N] ; //sum[i][]表示第i行的前缀和
inline int solve ( int h , int x , int y ) {
return sum[h][y] - sum[h][x-1] ;
}
inline void next ( int &p1 ,int x , int y ) {
while ( solve( p1 , x , y ) != 0 && p1 < n ) p1 ++ ;
}
int main() {
cin >> n ;
for ( int i = 1 ; i <= n ; i ++ ) {
scanf ( "%s" , st + 1 ) ;
for ( int j = 1 ; j <= n ; j ++ )
sum[i][j] = sum[i][j-1] + ( st[j] == 'W' ? 0 : 1 ) ; //得到前缀和
}
int ans = 0 ;
for ( int l = 1 ; l <= n ; l ++ ) // 枚举两列
for ( int r = l ; r <= n ; r ++ ) {
int p1 = 1 ; next ( p1 , l , r ) ; //得到第一个满足条件的
for ( int p2 = p1 ; p2 <= n ; p2 ++ ) { //从当前这一个开始搜索
if ( p2 < p1 ) continue ; //如果p2直接跳到p1后面去了,那么就p2++
if ( solve ( p2 , l , r ) != 0 ) { //如果当前这一行不满足要求
p1 = p2 + 1 ; next( p1 , l , r ) ; //尾往后跳
if ( solve ( p1 , l , r ) != 0 ) break ; //如果没有找到,就直接退出
}
if ( solve ( p2 , l , r ) == 0 ) { // 如果满足条件,就将以p2结尾的开头在p1以内的所有矩阵记录一下
ans += ( p2 - p1 + 1 ) ;
}
}
}
cout << ans << endl ; //最后输出
return 0 ;
}