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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章