矩形
题目链接:https://www.luogu.com.cn/problem/P1191
题意
有一个n*n的字符矩阵,每个位置为’B’或’W’,求’W’形成的矩阵的数量。
题解:
设
h
[
i
]
[
j
]
h[i][j]
h[i][j],代表第i行,第j列,向上有多少个连续的’W’。
思路一:单调栈。对于每一行,维护一个递增的单调栈,每个维护高度和这个高度的列的数量。然后对于
h
[
i
]
[
j
]
h[i][j]
h[i][j],如果它大于等于栈顶高度,则将其放入栈中,同高度需要合并。如果小于栈顶高度,则弹出元素,统计矩形数量。
思路二:暴力。同样的,和单调栈一行先求出每一行以当前行为底,每列‘W’最多的数量。然后枚举左下角,暴力求右下角,统计总数。对于当前第i行第j列的元素,考虑将其作为左下角,设height为高度的最小值,从j依次遍历至n,每次更新height值,同时将结果加上height(代表以第i行为底,第j列为左下角,遍历至当前列时,总有height中不同的矩形,长已确定,宽可以为1~height)。时间复杂度应该是O(n3)。
单调栈代码:
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<ctype.h>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<iterator>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = 200;
const int mod = 998244353;
struct node{
int h, num;
node(){}
node(int a, int b):h(a),num(b){}
}st[maxn];
char str[maxn][maxn];
int a[maxn][maxn];
int main()
{
int n, i, j, k, top;
LL ans=0;
scanf("%d", &n);
for(i=1;i<=n;i++)
{
scanf("%s", str[i]);
for(j=0;j<n;j++)
if(str[i][j] == 'B')a[i][j] = 0;
else a[i][j] = a[i-1][j]+1;
}
for(i=1;i<=n;i++)
{
top = 0;
st[0].h = 0;
for(j=0;j<n;j++)
{
int num = 1;
while(top && a[i][j] < st[top].h)
{
node e = st[top];
if(st[top-1].h > a[i][j])
{
ans+=(e.h-st[top-1].h)*(e.num*(e.num+1)/2);
st[top-1].num += e.num;
}
else
{
ans+=(e.h-a[i][j])*(e.num*(e.num+1)/2);
num += e.num;
}
top--;
}
if(a[i][j] == st[top].h)
st[top].num += num;
else st[++top] = node(a[i][j], num);
}
while(top)
{
node e = st[top];
ans += (e.h-st[top-1].h) * (e.num * (e.num+1)/2);
st[top-1].num += e.num;
top--;
}
}
printf("%lld\n", ans);
return 0;
}
暴力代码:
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<ctype.h>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<iterator>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = 200;
const int mod = 998244353;
char str[maxn];
int h[maxn];
int main()
{
int n, i, j, k;
LL ans = 0;
scanf("%d", &n);
for(i=0;i<n;i++)
{
scanf("%s", str);
for(j=0;j<n;j++)
if(str[j] == 'B')h[j] = 0;
else h[j]++;
for(j=0;j<n;j++)
{
int hei = h[j];
for(k=j;k<n;k++)
{
if(h[k] == 0)break;
hei = min(hei, h[k]);
ans += hei;
}
}
}
printf("%lld\n", ans);
return 0;
}