HDU 2870 Largest Submatrix 单调队列优化DP?单调栈!

版权声明:https://blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/89949972

title

HDU 2870
Problem Description

Now here is a matrix with letter ‘a’,‘b’,‘c’,‘w’,‘x’,‘y’,‘z’ and you can change ‘w’ to ‘a’ or ‘b’, change ‘x’ to ‘b’ or ‘c’, change ‘y’ to ‘a’ or ‘c’, and change ‘z’ to ‘a’, ‘b’ or ‘c’. After you changed it, what’s the largest submatrix with the same letters you can make?

Input

The input contains multiple test cases. Each test case begins with m and n (1 ≤ m, n ≤ 1000) on line. Then come the elements of a matrix in row-major order on m lines each with n letters. The input ends once EOF is met.

Output

For each test case, output one line containing the number of elements of the largest submatrix of all same letters.

Sample Input

2 4
abcw
wxyz

Sample Output

3

Source

2009 Multi-University Training Contest 7 - Host by FZU

Recommend

gaojie | We have carefully selected several similar problems for you: 2830 2577 1505 2845 1069

analysis

书上标明的是单调队列优化 D P DP ,然而我好像没用到单调队列?不懂哎。。

看题看了一小时,没有任何思路,只好去翻了题解,原来这么简单。我真服自己了。看来还是对模型不够熟悉啊,得加把劲儿了。。

正式题解:w x y z 可以各自 变成a ,b ,c 中的几种, 那么只需要考虑矩阵由 a, b 或 c 构成就可以了。

对于每一种情况都枚举一次(一共也就三种), 比如现在考虑由 a 构成的矩阵, 只需要将能 w y z a 的位置记为 1, 其他位置记为 0 ,然后找面积最大的 由 1 组成的矩阵即可。

那么这题就要用到单调栈不会的同学可以去这边学其实我也不会

code

没用单调栈,耗时280MS

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
    x=0;
    T f=1, ch=getc();
    while (!isdigit(ch) && ch^'-') ch=getc();
    if (ch=='-') f=-1, ch=getc();
    while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getc();
    x*=f;
}

template<typename T>inline void write(T &x)
{
	if (!x) { putchar('0'),putchar('\n'); return ; }
	if (x<0) putchar('-'),x=-x;
	T num=0,ch[16];
	while (x) ch[++num]=x%10+48,x/=10;
	while (num) putchar(ch[num--]);
	putchar('\n');
}

char s[maxn][maxn],key[maxn][maxn];
int l[maxn],r[maxn],cnt[maxn][maxn],n,m,ans;
inline void solve(char x,char a,char b,char c)
{
	for (int i=1; i<=n; ++i)
		for (int j=1; j<=m; ++j)
			if (s[i][j]==a || s[i][j]==b || s[i][j]==c) key[i][j]=x;
			else key[i][j]=s[i][j];

	for (int i=1; i<=n; ++i)
	{
		cnt[i][0]=cnt[i][m+1]=-1;

		for (int j=1; j<=m; ++j)
		{
			l[j]=r[j]=j;
			if (key[i][j]^x) cnt[i][j]=0;
			else cnt[i][j]=cnt[i-1][j]+1;
		}

		for (int j=2; j<=m; ++j)
			if (cnt[i][j])
				while (cnt[i][l[j]-1]>=cnt[i][j]) l[j]=l[l[j]-1];

		for (int j=m-1; j; --j)
			if (cnt[i][j])
				while (cnt[i][r[j]+1]>=cnt[i][j]) r[j]=r[r[j]+1];

		for (int j=1; j<=m; ++j)
			if (cnt[i][j]) ans=max(ans,(r[j]-l[j]+1)*cnt[i][j]);
	}
}

int main()
{
	while (~scanf("%d %d",&n,&m))
	{
		for (int i=1; i<=n; ++i) scanf("%s",s[i]+1);
		ans=0;
		solve('a','w','y','z');
		solve('b','w','x','z');
		solve('c','x','y','z');
		write(ans);
	}
	return 0;
}

用了单调栈,耗时312MS,怎么还慢了

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
    x=0;
    T f=1, ch=getc();
    while (!isdigit(ch) && ch^'-') ch=getc();
    if (ch=='-') f=-1, ch=getc();
    while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getc();
    x*=f;
}

template<typename T>inline void write(T &x)
{
	if (!x) { putchar('0'),putchar('\n'); return ; }
	if (x<0) putchar('-'),x=-x;
	T num=0,ch[16];
	while (x) ch[++num]=x%10+48,x/=10;
	while (num) putchar(ch[num--]);
	putchar('\n');
}

char a[maxn][maxn];
int cnt[maxn][maxn];
inline int fun(char a,char b)
{
	if (b=='a' && (a=='a' || a=='w' || a=='y' || a=='z') ) return 1;
	if (b=='b' && (a=='b' || a=='w' || a=='x' || a=='z') ) return 1;
	if (b=='c' && (a=='c' || a=='x' || a=='y' || a=='z') ) return 1;
	return 0;
}

int s[maxn],top;
int l[maxn],r[maxn];
int num[maxn],n,m,ans;
inline void solve()
{
	memset(num,0,sizeof(num));
	for (int i=1; i<=n; ++i)
	{
		for (int j=1; j<=m; ++j)
			if (cnt[i][j]) ++num[j];
			else num[j]=0;

		top=0;
		for (int j=1; j<=m; ++j)
		{
			int lef=0;
			while (top)
			{
				lef=s[top];
				if (num[lef]>=num[j]) --top;
				else break;
			}
			s[++top]=j,l[j]=lef;
		}
		
		top=0;
		for (int j=m; j>=1; --j)
		{
			int rig=m+1;
			while (top)
			{
				rig=s[top];
				if (num[rig]>=num[j]) --top;
				else break;
			}
			s[++top]=j,r[j]=rig;
		}
		
		for (int j=1; j<=m; ++j) ans=max(ans,num[j]*(r[j]-l[j]-1));
	}
}

int main()
{
	while (~scanf("%d %d",&n,&m))
	{
		for (int i=1; i<=n; ++i) scanf("%s",a[i]+1);
		ans=0;
		for (char k='a'; k<='c'; ++k)
		{
			for (int i=1; i<=n; ++i)
				for (int j=1; j<=m; ++j)
					if (fun(a[i][j],k)) cnt[i][j]=1;
					else cnt[i][j]=0;
			solve();
		}
		write(ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/huashuimu2003/article/details/89949972