洛谷_P1191 矩形(单调栈 || 暴力)

矩形

题目链接: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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值