题意:
给定1片高为n,宽为m的矩形,每个格由一种颜色构成.
在矩形中最多可以找到的旗子数目.
旗子:由三种颜色构成,且三种颜色宽度相同,每个颜色横方向颜色全相同
解析:
预处理每个点下方相同颜色最大,右边相同颜色最大
然后遍历每个点,对于同一点,如果呢里有棋子,呢么它的旗子高度是确定的,高度等于该点down[i][j]*3
有三个要求满足,才能有1面棋子:
1.i+down[i][j]*3+1<=n//旗子预设没有超过上限
2.down[i][j]!=down[i+down[i][j]][j]//第1,第2种颜色宽度相同
3.down[i][j]>down[i+2*down[i][j]][j]//第3种颜色大于等于第1种
然后遍历得每一层的最小长度为以(i,j)为左上顶点可以选择的旗子数目
ac:
#include<bits/stdc++.h>
#define ll long long
#define MAXN 1005
using namespace std;
char mp[MAXN][MAXN];
int down[MAXN][MAXN];
int weig[MAXN][MAXN];
int n,m;
void solve()//预处理每个点下最大相同长度,右最大相同长度
{
for(int i=1;i<=n;i++)
for(int j=m;j>=1;j--)
if(mp[i][j]==mp[i][j+1])
weig[i][j]=weig[i][j+1]+1;
else
weig[i][j]=1;
for(int i=n;i>=1;i--)
for(int j=1;j<=m;j++)
if(mp[i][j]==mp[i+1][j])
down[i][j]=down[i+1][j]+1;
else
down[i][j]=1;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%s",mp[i]+1);
solve();
ll ans=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(i+3*down[i][j]-1>n)//旗子预设没有超过上限
continue;
if(down[i][j]!=down[i+down[i][j]][j])//第1,第2种颜色宽度相同
continue;
if(down[i][j]>down[i+2*down[i][j]][j])//第3种颜色大于等于第1种
continue;
int len=1e9;
for(int k=i;k<=i+3*down[i][j]-1;k++)//遍历允许的最大长度
len=min(len,weig[k][j]);
ans+=len;
}
}
printf("%lld\n",ans);
return 0;
}