C. Flag(预处理的dp)

我的dp真是菜的一笔

你 不 会 不 预 处 理 就 想 D P 吧 ? 你不会不预处理就想DP吧? DP?

首先不预处理根本无法判断子矩阵是否满足要求

而且设计状态的时候必须把子矩阵的大小设计进去,这样的话空间是 O ( 100 0 4 ) O(1000^4) O(10004)

考 虑 预 处 理 , 处 理 a [ i ] [ j ] 表 示 ( i , j ) 最 多 往 上 延 伸 几 个 点 是 同 色 的 考虑预处理,处理a[i][j]表示(i,j)最多往上延伸几个点是同色的 ,a[i][j](i,j)

那 么 以 ( i , j ) 为 右 下 角 矩 阵 的 合 法 方 案 那么以(i,j)为右下角矩阵的合法方案 (i,j)

先 考 虑 单 列 \color{Red}先考虑单列

设 k = a [ i ] [ j ] , 那 么 a [ i − k ] [ j ] 也 要 等 于 k 设k=a[i][j],那么a[i-k][j]也要等于k k=a[i][j],a[ik][j]k

而 且 a [ i − 2 ∗ k ] [ j ] 要 大 于 等 于 k ( 最 上 面 那 层 多 了 可 以 不 选 ) 而且a[i-2*k][j]要大于等于k(最上面那层多了可以不选) a[i2k][j]k()

这 样 的 话 单 列 就 有 一 种 方 案 了 这样的话单列就有一种方案了

考 虑 多 列 \color{Red}考虑多列

多 列 就 从 j − 1 列 转 移 过 来 就 好 了 多列就从j-1列转移过来就好了 j1

先 判 断 颜 色 是 否 相 同 , 在 判 断 长 度 , 具 体 看 代 码 先判断颜色是否相同,在判断长度,具体看代码 ,,

#include <bits/stdc++.h>
using namespace std;
const int maxn=1009;
char mp[maxn][maxn];
int n,m,a[maxn][maxn],f[maxn][maxn],ans;
int main()
{
	cin >> n >> m;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
		cin >> mp[i][j];
	//数组a预处理每个格子往上最多几个格子和自己相同 
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	{
		if( i==1 || mp[i][j]!=mp[i-1][j] )	a[i][j]=1;
		else	a[i][j]=a[i-1][j]+1;
	}
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	{
		int k=a[i][j],mid=i-k,up=i-2*k;//以这个作为右下角,子矩阵必须高3k
		if( a[mid][j]!=k || a[up][j]<k )	continue;
		f[i][j]=1;//单列
		if( mp[i][j-1]==mp[i][j]&&mp[mid][j-1]==mp[mid][j]&&mp[up][j-1]==mp[up][j] )
		{
			if( a[i][j-1]==k&&a[mid][j-1]==k&&a[up][j-1]>=k )
				f[i][j]+=f[i][j-1];
		}
		ans+=f[i][j];
	}
	cout << ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值