C. Flag(预处理的dp)

我的dp真是菜的一笔

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

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

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

, a [ i ] [ j ] ( i , j ) 考虑预处理,处理a[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

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

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

\color{Red}考虑多列

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

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

#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;
}

猜你喜欢

转载自blog.csdn.net/jziwjxjd/article/details/107756741