洛谷P1191 矩形

题目描述

给出一个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 ;
}

猜你喜欢

转载自blog.csdn.net/zsyzClb/article/details/84886769
今日推荐