1. 程式人生 > >HDU - 4495 Rectangle 暴力列舉+預處理

HDU - 4495 Rectangle 暴力列舉+預處理

Given a rectangle which contains N rows and each of them contains a string length of M.
You must find out a symmetrical isosceles right triangle (with two equal edges and a right angle) with two edges parallel two side of the rectangle. Symmetry means the value should be the same according to the shortest altitude of the triangle. And just output the area of the triangle.

Input

The first line of the input contains an integer T (1 <= T <= 20), which mean there are T test case follow.
For each test case, the first line contains two integer number N and M (1 <= N, M <= 500) which means described above.
And then N lines follow, which contains a string of length M. The string only contains letters or digits.

Output

For each test case, output a single integer that is the answer to the problem described above.

Sample Input

1 
4 4 
abab 
dacb 
adab 
cabb

Sample Output

6

題目連結:點選檢視

題意:給出n*m的矩陣,只包含字母和數字,求最大的對稱的等腰三角形的面積

題解:對於每個位置,先預處理出對於每個位置斜著對應奇數對稱和偶數對稱的最大個數,然後暴力列舉每個位置,以這個位置為直角邊,分別求4個方向的最大等腰三角形即可

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
int n,m;
char mp[510][510];
int mpji[510][510][2];
int mpou[510][510][2];
int cul(int x1,int y1,int x2,int y2,int kx1,int ky1,int kx2,int ky2)
{
	int ans=0;
//	cout<<x1<<" "<<y1<<" "<<x2<<" "<<y2<<endl;
	while(x1>0&&x1<=n&&x2>0&&x2<=n&&y1>0&&y1<=m&&y2>0&&y2<=m)
	{
	//	cout<<x1<<" "<<y1<<" "<<x2<<" "<<y2<<endl;
	//	cout<<mp[x1][y1]<<" "<<mp[x2][y2]<<endl;
		if(mp[x1][y1]==mp[x2][y2]) ans+=2;
		else break;
		
		x1+=kx1;
		y1+=ky1;
		x2+=kx2;
		y2+=ky2;
	}
	return ans;
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)
			scanf("%s",mp[i]+1);
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				mpji[i][j][0]=cul(i,j,i,j,-1,1,1,-1)-1;
				mpji[i][j][1]=cul(i,j,i,j,-1,-1,1,1)-1;
				
				mpou[i][j][0]=cul(i,j,i+1,j-1,-1,1,1,-1);
				mpou[i][j][1]=cul(i,j,i+1,j+1,-1,-1,1,1);
				
		//		cout<<mpou[i][j][0]<<" "<<mpou[i][j][1]<<endl;
			}
		}
		int ans=0;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				int cnt=0,flag=1;
				for(int k=1;;k++)
				{
					if(k&1)
					{
						if(i-k/2<=0||j-k/2<=0) break;
						if(mpji[i-k/2][j-k/2][0]>=k) cnt+=k;
						else break;
					}
					else
					{
						if(i-k/2<=0||j-k/2+1<=0) break;
						if(mpou[i-k/2][j-k/2+1][0]>=k) cnt+=k;
						else break;
					}
				}
				ans=max(ans,cnt);
				
				cnt=0;
				for(int k=1;;k++)
				{
					if(k&1)
					{
						if(i-k/2<=0||j+k/2>m) break;
						if(mpji[i-k/2][j+k/2][1]>=k) cnt+=k;
						else break;
					}
					else
					{
						if(i-k/2<=0||j+k/2-1>m) break;
						if(mpou[i-k/2][j+k/2-1][1]>=k) cnt+=k;
						else break;
					}
				}
				ans=max(ans,cnt);
				
				cnt=0;
				for(int k=1;;k++)
				{
					if(k&1)
					{
						if(i+k/2>n||j-k/2<=0) break;
						if(mpji[i+k/2][j-k/2][1]>=k) cnt+=k;
						else break;
					}
					else
					{
						if(i+k/2-1>n||j-k/2<=0) break;
						if(mpou[i+k/2-1][j-k/2][1]>=k) cnt+=k;
						else break;
					}
				}
				ans=max(ans,cnt);
				
				cnt=0;
				for(int k=1;;k++)
				{
					if(k&1)
					{
						if(i+k/2>n||j+k/2>m) break;
						if(mpji[i+k/2][j+k/2][0]>=k) cnt+=k;
						else break;
					}
					else
					{
					//	cout<<mpou[i+k/2-1][j+k/2][1]<<endl;
						if(i+k/2-1>n||j+k/2>m) break;
						if(mpou[i+k/2-1][j+k/2][0]>=k) cnt+=k;
						else break;
					}
				}
				ans=max(ans,cnt);
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}
/*
4 4
cbca
bada
cdbb
accc
*/