问题描述
给定一个字母矩阵,定义一个LQ三角形为某行中连续的几个字母、某列中连续的几个字母和一条45度的斜线中连续的几个字母组成的等腰直角三角形的边缘部分,其中每条边上的字母数量相等且至少为2 。
例如,对于下面的字母矩阵中,所有的字母 L 组成一个LQ三角形,所有字母 Q 组成了一个 LQ 三角形,所有字母 C 也组成了一个 LQ 三角形。
AAAAAAA
ALLLLLA
ALQQLAA
ALQLAAC
ALLAACC
ALAACCC
如果一个 LQ 三角形边上的所有字母相等,则称为一个全相等三角形。以三个例子都是全相等三角形。
给定一个字母矩阵,请求其中有多少个全相等三角形。
输入格式
输入第一行包含两个整数 n, m,分别表示字母矩阵的行数和列数。
接下来 n 行,每行 m 个大写字母,为给定的矩阵。
输出格式
输出一行,包含一个整数,表示答案。
样例输入1
3 4
AAAA
ALAQ
ALQQ
样例输出1
4
样例输入2
6 7
AAAAAAA
ALLLLLA
ALQQLAA
ALQLAAC
ALLAACC
ALAACCC
样例输出2
23
评测用例规模与约定
对于50%的评测用例,1 < = n , m < = 10 1<=n,m<=101<=n,m<=10。
对于所有评测用例,1 < = n , m < = 100 1<=n,m<=1001<=n,m<=100。
思路:这道题分四种情况可以使三角形全等
分别是直角顶点在左上角,右上角,左下角,右下角
当顶点在右下角时
需要判断左顶点和上顶点这条斜边上所有的点是否相等,和左顶点到右下角直角顶点这条边与上顶点到右下角直角顶点这条边上的所有点是否相等
当顶点在左下角
当顶点在右上角
当顶点在左上角
这四种情况思路是一样的,注意的是我们可以求得每行每列最多相同的点的个数,对代码复杂度进行优化
n,m = map(int,input().split())
mp=[]
for i in range(n):
mp.append(input())
ans=0
def check(x,y,a,b,d):
if d==0:
#定右顶点,左顶点为(x,y),上顶点为(a,b)
while x>=a and y<=b:
if mp[a][b] != mp[x][y]:return False
if mp[a][b]==mp[x][y]
x-=1
y+=1
elif d==1:
#定左顶点,右顶点为(x,y),上顶点为(a,b)
while x>=a and y>=b:
if mp[a][b] != mp[x][y]:
return False
x-=1
y-=1
elif d==2:
#定右上顶点,左顶点为(x,y),下顶点为(a,b)
while x<=a and y<=b:
if mp[a][b] != mp[x][y]:return False
x+=1
y+=1
elif d==3:
#定左上顶点,右顶点为(x,y),下顶点为(a,b)
while x<=a and y>=b:
if mp[a][b] != mp[x][y]:return False
x+=1
y-=1
return True
#得到上下左右最大的数 缩小范围
for i in range(n):
for j in range(m):
up,down,left,right=0,0,0,0
while (i-up)>=0 and mp[i-up][j]==mp[i][j]:
up+=1
while (i+down)<n and mp[i+down][j] == mp[i][j]:
down+=1
while (j-left)>=0 and mp[i][j-left] == mp[i][j]:
left+=1
while (j+right)<m and mp[i][j+right] == mp[i][j]:
right+=1
#再确定三角形遍历的范围 减少遍历次数
for k in range(1,min(up,left)):
if check(i,j-k,i-k,j,0):#当满足这个条件时 说明mp[i][j-1]=mp[i-1][j] 一直到mp[i][j-k]=mp[i-k][j]这些都是一一对应相等的
#从而间接判断出两条直角边都是相等的
ans+=1
for k in range(1,min(right,up)):
if check(i,j+k,i-k,j,1):
ans+=1
for k in range(1,min(left,down)):
if check(i,j-k,i+k,j,2):
ans+=1
for k in range(1,min(right,down)):
if check(i,j+k,i+k,j,3):
ans+=1
print(ans)