题解:P3135 [USACO16JAN] Fort Moo P
shaozhehan · · 题解
原题链接
题目大意:
现给定一个
思路:
使用前缀和优化暴力的算法可以通过本题,时间复杂度为
我们先枚举矩阵的左上角和右下角的横坐标,不妨设左上角的横坐标为
上代码:
#include <iostream>
using namespace std;
char mp[201][201];
int pre_row[201][201], pre_column[201][201], column[201];
int main(){
cin.tie(NULL);
ios_base::sync_with_stdio(false);// cin、cout 优化
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++){
for (int j = 1; j <= m; j++){
cin >> mp[i][j];
}
}
// 预处理前缀和
for (int i = 1; i <= n; i++){
for (int j = 1; j <= m; j++){
pre_row[i][j] = pre_row[i][j - 1];
if (mp[i][j] == 'X'){
pre_row[i][j]++;
}
}
}
for (int i = 1; i <= n; i++){
for (int j = 1; j <= m; j++){
pre_column[i][j] = pre_column[i - 1][j];
if (mp[i][j] == 'X'){
pre_column[i][j]++;
}
}
}
int ans = 0;
for (int i = 1; i <= n; i++){
for (int k = i; k <= n; k++){
// 预处理出所有满足条件的纵坐标
int sz_column = 0;
for (int j = 1; j <= m; j++){
if (pre_column[k][j] == pre_column[i - 1][j]){
column[++sz_column] = j;
}
}
int lft = 1, rght = 1;
while (lft <= sz_column){
if (mp[i][column[lft]] == 'X' || mp[k][column[lft]] == 'X'){// 如果满足条件的纵坐标已经找完
break;
}
rght = lft;
while (rght < sz_column && pre_row[i][column[rght + 1]] == pre_row[i][column[lft] - 1] && pre_row[k][column[rght + 1]] == pre_row[k][column[lft] - 1]){// 判断横向的边框上没有 X
rght++;
}
ans = max(ans, (k - i + 1) * (column[rght] - column[lft] + 1));
lft = rght + 1;
while (lft < sz_column && mp[i][column[lft]] == 'X'){// 继续寻找新的起点
lft++;
}
}
}
}
cout << ans << "\n";
return 0;
}