C. Flag(简单dp)

C - Flag

题意:

给定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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值