题意:输入一个 n∗m(1≤n,m≤1000) 矩阵,每个格子可能是空地,也可能是沼泽。对于每个空地格子,求出以它为右下角的空矩形的最大周长,然后统计每个周长出现了多少次。下图中标注了3个位置的最大空矩形,其周长分别是6,10,12.如果统计完所有20个空地,答案是6*4(表示周长为4的矩形有6个)、5*6、3*10、1*12。(本段摘自《算法竞赛入门经典(第2版)》)
分析:
分析详见《算法竞赛入门经典(第2版)》。在组织单调栈时要注意并非所有元素都要入栈,栈顶元素始终保持为当前最优即可。
代码:
#include <fstream>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <stack>
#include <sstream>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <vector>
#include <set>
#include <string>
#include <vector>
using namespace std;
const int maxn = 1000 + 5;
int T, n, m, tmp, l;
int h[maxn];
char a[maxn][maxn];
map< int, int > M;
int main()
{
scanf("%d", &T);
for (int C = 0; C < T; ++C)
{
M.clear();
memset(h, 0, sizeof(h));
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i)
scanf("%s", a[i] + 1);
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= m; ++j)
if (a[i][j] == '.')
++h[j];
else
h[j] = 0;
stack< pair<int, int> > sta;
for (int j = 1; j <= m; ++j)
{
if (h[j] > 0)
{
pair< int, int > cur(j, h[j]);
while (!sta.empty() && sta.top().second >= cur.second)
{
cur.first = sta.top().first;
sta.pop();
}
if (sta.empty() || sta.top().second - sta.top().first < cur.second - cur.first)
sta.push(cur);
++M[j - sta.top().first + 1 + sta.top().second];
}
else
while (!sta.empty())
sta.pop();
}
}
for (map< int, int >::iterator it = M.begin(); it != M.end(); ++it)
printf("%d x %d\n", it->second, it->first * 2);
}
return 0;
}