hdu2870 Largest Submatrix 1506 1505

本文探讨了在矩阵中通过变换特定字符以形成最大相同字母子矩阵的问题,并提供了求解方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Largest Submatrix

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


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
 
将全部字符依次转化a, b, c, 再分别求出这三个矩阵的最大子矩阵即可.

思路:枚举后转换为 hdu 1505 hdu 1506 的情况。

可以转化为a的有:w,y, z

可以转化为b的有:w,x, z

可以转换为c的有:x, y, z

所以

a, w,  y, z一组

b, w,  x, z一组

c, x,  y,  z一组

分别dp


///对于每一个a[i],用dp找出a[i]左边和右边连续大于自己的数的长度    
///l[i]表示比a[i]大的数连续的最左边的位置    
///r[i]表示比a[i]大的数连续的最右边的位置  
#include<iostream>    
#include<cstring>    
#include<algorithm>  
using namespace std;    
int l[1005],r[1005];   
int MAX;
char str[1005][1005];  
int h[1005][1005];
int m,n,MAXANS;
void DP()
{
	int i;
	for(int x=1;x<=m;++x)
	{
		l[1]=1;
		r[n]=n;
		for(i=2;i<=n;++i)  
		{  
			int t=i;  
			while(t>1&&h[x][i]<=h[x][t-1])  
				t=l[t-1];  
			l[i]=t;  
		} 

		for(i=n-1;i>=1;--i)  
		{  
			int t=i;  
			while(t<n&&h[x][i]<=h[x][t+1])  
				t=r[t+1];  
			r[i]=t;  
		} 

		MAX=0; 
		for(i=1;i<=n;++i)  
			if((r[i]-l[i]+1)*h[x][i]>MAX)  
				MAX=(r[i]-l[i]+1)*h[x][i]; 
		if(MAX>MAXANS)
			MAXANS=MAX;
	}  
}
int main()    
{  
	while(cin>>m>>n)  
	{  
		int i,j;  
		for(i=1;i<=m;++i)  
			cin>>str[i]+1;  
		MAXANS=0;
		for(i=1;i<=m;++i)
		{
			for(j=1;j<=n;++j)
			{
				if(str[i][j]=='a'||str[i][j]=='w'||str[i][j]=='z'||str[i][j]=='y')
					h[i][j]=h[i-1][j]+1;
				else
					h[i][j]=0;
			}
		}
		DP();
		for(i=1;i<=m;++i)
		{
			for(j=1;j<=n;++j)
			{
				if(str[i][j]=='b'||str[i][j]=='w'||str[i][j]=='z'||str[i][j]=='x')
					h[i][j]=h[i-1][j]+1;
				else
					h[i][j]=0;
			}
		}
		DP();
		for(i=1;i<=m;++i)
		{
			for(j=1;j<=n;++j)
			{
				if(str[i][j]=='c'||str[i][j]=='x'||str[i][j]=='y'||str[i][j]=='z')
					h[i][j]=h[i-1][j]+1;
				else
					h[i][j]=0;
			}
		}
		DP();
		cout<<MAXANS<<endl;  
	}  
}  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值