ACM程序设计选修课——1057: Beautiful Garden(模拟+耐心调试)

1057: Beautiful Garden

Time Limit: 5 Sec   Memory Limit: 128 MB
Submit: 25   Solved: 12
[ Submit][ Status][ Web Board]

Description

There's a beautiful garden whose size is  n  × m  in Edward's house. The garden can be 
partitioned  into  n  ×  m  equal-sized  square  chunks.  There  are  some  kinds  of  flowers 
planted in each square chunk which can be represented by using lowercase letters.
However, Edward thinks the garden is not beautiful enough. Edward wants to build a 
water  pool  in  the  garden.  So  that  the  garden  would  look  like  symmetric  (both 
horizontally and vertically). The water pool is a rectangle whose size is  p  × q  and the 
center of the water pool is also the center of the garden.
Something else important you should know is:
  n, m, p and q are all even.
  p is always less than n.
  q is always less than m.
  The borders of the water pool are parallel to the border of garden.
Edward wants to know how many different pairs of (p, q) he can choose.

Input

There are multiple test cases. The first line of input contains an integer  T  indicating 
the number of test cases. For each test case:
The first line contains two integers  n  and  m  (1 <=  n,  m  <= 2000,  n  and  m  are even), 
indicating  the  size  of  the  garden.  For  next  n  lines,  each  line  contains  m  characters 
showing the garden.
It is guaranteed that only lowercase letters will appear.

Output

For  each  test  case,  output  an  integer  indicating  the  number  of  choices  to  build  the 
water pool.

Sample Input

3
6 8
acbbbbca
dcaccacd
cdaddadc
cdaddadc
dcaccacd
acbbbbca
6 8
acbcbbca
dcaccacd
cdaddadc
cdaddadc
dcaccacd
acbbbbca
6 8
acbbbbca
dcadcacd
cdaddadc
cdaddadc
dcaccacd
acbbbbca

Sample Output

6
0
3

HINT

For the first sample, you have following six choices (blank rectangle means the water 

pool): 

很蛋疼的一道题,需要仔细调试。还有具体怎么计算呢?若下标均从0开始,显然上面的可抹除部分有2行(1与2),3列(1,2,3),那么答案就是2*3,其他情况均用这种办法求解。

代码:

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<string>
#include<deque>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
char pos[2009][2009];
int hang,lie;
inline bool huiwen(const char s[])
{
	int len=strlen(s);
	int i;
	for (i=0; i<len/2;i++)
	{
		if(s[i]!=s[len-1-i])
			return false;
	}
	return true;
}
int main(void)
{
	int t,i,j,l,r;
	scanf("%d",&t);
	while (t--)
	{
		memset(pos,0,sizeof(pos));
		scanf("%d%d",&hang,&lie);
		for (i=0; i<hang; i++)
		{
			scanf("%s",pos[i]);
		}
		l=hang/2-1;
		r=lie/2-1;
		for (i=0; i<hang/2; i++)//判断上下是否相同且回文
		{
			if( (strcmp(pos[i],pos[hang-1-i])!=0) || (!huiwen(pos[i])) || (!huiwen(pos[hang])))
			{
				l=i;
				break;
			}
		}
		bool ok=0;
		for (i=0; i<lie/2; i++)//列相同判断
		{
			for (j=l; j<=hang-1-l; j++)
			{
				if(pos[j][i]!=pos[j][lie-1-i])
				{
					r=i;
					ok=1;
					break;
				}
			}
			if(ok)
				break;
		}		
		for (i=0; i<r; i++)//列回文判断(放到上面的for里十分麻烦,独立出来判断)
		{
			for (j=l; j<hang/2; j++)
			{
				if(pos[j][i]!=pos[hang-1-j][i])
				{
					r=min(r,i);//肯定要取小的那列
					ok=1;
					break;
				}
			}
			if(ok)
				break;
		}
		printf("%d\n",l*r);//输出答案
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值