hdu2870(dp+单调栈优化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2870

Largest Submatrix

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2835    Accepted Submission(s): 1373


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
 

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


思路:我的第一道单调栈题。之前看了白书上的例题,但不是特别理解,这次正好重新又学了一遍。

这道题和hdu1505十分相似,就是相当于统计三遍。也就是分别把矩阵中的w,x,y,z全转成a,b,c。然后算三次。为了计算方便,把字母矩阵换成01矩阵,见代码。值得注意的是,经典的单调栈中每个元素的高度h[i]是一维的,而这题是二维的,用h[i][j]记录即可,每一行都用一次单调栈即可,详见代码。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
char s[1010][1010];
int scopy[1010][1010];
int h[1010][1010];
int l[1010];
int r[1010];
int st[1010];
int n,m;
ll ans1;
ll ans2;
ll ans3;
ll solve1()
{
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<m;j++)
		{
			if(s[i][j]=='a'||s[i][j]=='w'||s[i][j]=='y'||s[i][j]=='z')
			{
				scopy[i][j]=1;
			}
			else
			{
				scopy[i][j]=0;
			}
			if(scopy[i][j]==1)
			{
				h[i][j]=h[i-1][j]+1;
			}
			else
			h[i][j]=0;
		}
	}
	ans1=0;
	int t;
	for(int i=1;i<=n;i++)
	{
		t=0;
		for(int j=0;j<m;j++)
		{
			while(t>0&&h[i][st[t-1]]>=h[i][j])
			t--;
			l[j]= t==0 ? 0 : (st[t-1]+1);
			st[t++]=j;
		}
		t=0;
		for(int j=m-1;j>=0;j--)
		{
			while(t>0&&h[i][st[t-1]]>=h[i][j])
			t--;
			r[j]= t==0 ? m : st[t-1];
			st[t++]=j;
		}
		for(int j=0;j<m;j++)
		ans1=max(ans1,(ll)(h[i][j]*(r[j]-l[j])));
	}
	return ans1;
}
ll solve2()
{
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<m;j++)
		{
			if(s[i][j]=='b'||s[i][j]=='w'||s[i][j]=='x'||s[i][j]=='z')
			{
				scopy[i][j]=1;
			}
			else
			{
				scopy[i][j]=0;
			}
			if(scopy[i][j]==1)
			{
				h[i][j]=h[i-1][j]+1;
			}
			else
			h[i][j]=0;
		}
	}
	ans2=0;
	int t;
	for(int i=1;i<=n;i++)
	{
		t=0;
		for(int j=0;j<m;j++)
		{
			while(t>0&&h[i][st[t-1]]>=h[i][j])
			t--;
			l[j]= t==0 ? 0 : (st[t-1]+1);
			st[t++]=j;
		}
		t=0;
		for(int j=m-1;j>=0;j--)
		{
			while(t>0&&h[i][st[t-1]]>=h[i][j])
			t--;
			r[j]= t==0 ? m : st[t-1];
			st[t++]=j;
		}
		for(int j=0;j<m;j++)
		ans2=max(ans2,(ll)(h[i][j]*(r[j]-l[j])));
	}
	return ans2;
}
ll solve3()
{
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<m;j++)
		{
			if(s[i][j]=='c'||s[i][j]=='x'||s[i][j]=='y'||s[i][j]=='z')
			{
				scopy[i][j]=1;
			}
			else
			{
				scopy[i][j]=0;
			}
			if(scopy[i][j]==1)
			{
				h[i][j]=h[i-1][j]+1;
			}
			else
			h[i][j]=0;
		}
	}
	ans3=0;
	int t;
	for(int i=1;i<=n;i++)
	{
		t=0;
		for(int j=0;j<m;j++)
		{
			while(t>0&&h[i][st[t-1]]>=h[i][j])
			t--;
			l[j]= t==0 ? 0 : (st[t-1]+1);
			st[t++]=j;
		}
		t=0;
		for(int j=m-1;j>=0;j--)
		{
			while(t>0&&h[i][st[t-1]]>=h[i][j])
			t--;
			r[j]= t==0 ? m : st[t-1];
			st[t++]=j;
		}
		for(int j=0;j<m;j++)
		ans3=max(ans3,(ll)(h[i][j]*(r[j]-l[j])));
	}
	return ans3;
}
int main()
{
	  while(scanf("%d%d",&n,&m)!=EOF)
   {
	   for(int i=1;i<=n;i++)
	   {
	      getchar();
		  scanf("%s",s[i]);
	   }
	   ll res=0;
	   ll t1=solve1();
	   ll t2=solve2();
	   ll t3=solve3();
	   res=max(t1,max(t2,t3));
	   printf("%lld\n",res);
   }
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/star_moon0309/article/details/80665878