蓝桥杯 2024 省赛 Python B 连连看题目解法解析:暴力解与高效正解探讨
题目描述
小蓝正在和朋友们玩一种新的连连看游戏。在一个 n×m 的矩形网格中,每个格子中都有一个整数,第 i 行第 j 列上的整数为 Ai,j。玩家需要在这个网格中寻找一对格子 (a,b) 和 (c,d) 使得这两个格子中的整数 Aa,b 和 Ac,d 相等,且它们的位置满足 ∣a−c∣=∣b−d∣>0。请问在这个 n×m 的矩形网格中有多少对这样的格子满足条件。
输入格式
输入的第一行包含两个正整数 n 和 m,用一个空格分隔。
接下来是 n 行,第 i 行包含 m 个正整数 Ai,1,Ai,2,…,Ai,m,相邻整数之间用一个空格分隔。
输出格式
输出一行包含一个整数表示答案。
输入输出样例
输入 #1复制
3 2 1 2 2 3 3 2
输出 #1复制
6
说明/提示
一共有以下 6 对格子:(1,2)−(2,1),(2,2)−(3,1),(2,1)−(3,2),(2,1)−(1,2),(3,1)−(2,2),(3,2)−(2,1)。
数据范围
对于 20% 的评测用例,1≤n,m≤50;
对于所有评测用例,1≤n,m≤1000,1≤Ai,j≤1000。
暴力解:
因为蓝桥杯的赛制与acm不同,通过部分的用例可以获得部分的分数,力求省赛获奖而不求进入国赛的选手(up),对于不会的题可以按照题意直接暴力求解,for循环只管套;例如本题中,需要找到满足|a-c| = |b -d|>0且整数A相等的格子的对数,暴力求解就完全遍历棋盘中的每一个整数,让它与其他的每一个整数运算一遍 ,看两者是否满足条件,满足就累加到ans中。
n,m = map(int,input().split())
matrix = []
for i in range(n):
row = list(map(int,input().split()))
matrix.append(row)
ans = 0
for i in range(n):
for j in range(m):
for ii in range(n):
for jj in range(m):
if (matrix[i][j] == matrix[ii][jj] and abs(i-ii) == abs(j-jj) and abs(i-ii) > 0):
ans += 1
print(ans)
因为涉及到两对坐标的运算,直接套4层循环,暴力解决,在暴力的同时加上剪枝等操作,就可以通过更多的用例,甚至是全部的用例,不过剪枝需要理解题目,去除不必要的循环,这一点就是题目的难点了,例如:
(b站)
n,m = map(int,input().split())
matrix = []
for i in range(n):
row = list(map(int,input().split()))
matrix.append(row)
ans = 0
l = [[0] * (2005) for _ in range(2005)]
r = [[0] * (2005) for _ in range(2005)]
for i in range(n):
for j in range(m):
ans += l[matrix[i][j]][i+j]
ans += r[matrix[i][j]][i-j]
l[matrix[i][j]][i + j] += 1
r[matrix[i][j]][i - j] += 1
print(ans*2)
还有别的思路,一个题可能有很多解法:
(解法来自C语言网)
m,n = map(int,input().split()) #m行n列
ans = 0
arr = []
for _ in range(m):
arr.append([int(i) for i in input().strip().split()])
#两条对角线,每条两个三角区域
#1
for i in range(m): #(i,j)为这条对角线的起点
temp = {} #这一条对角线中每个数字出现的次数
t = 0
j = 0
while 0<=i<m and 0<=j<n:
if arr[i][j] in temp:
t += temp[arr[i][j]] #相当与将这次的数字与之前所有数字配一次对
else:
temp[arr[i][j]] = 0
temp[arr[i][j]] += 1 #if和else两种情况都要执行
i -= 1
j += 1
ans += t
#2
for i in range(m):
temp = {}
t = 0
j = 0
while 0<=i<m and 0<=j<n:
if arr[i][j] in temp:
t += temp[arr[i][j]]
else:
temp[arr[i][j]] = 0
temp[arr[i][j]] += 1
i += 1
j += 1
ans += t
#3
for j in range(1,n):
temp = {}
t = 0
i = m-1
while 0<=i<m and 0<=j<n:
if arr[i][j] in temp:
t += temp[arr[i][j]]
else:
temp[arr[i][j]] = 0
temp[arr[i][j]] += 1
i -= 1
j += 1
ans += t
#4
for j in range(1,n):
temp = {}
t = 0
i = 0
while 0<=i<m and 0<=j<n:
if arr[i][j] in temp:
t += temp[arr[i][j]]
else:
temp[arr[i][j]] = 0
temp[arr[i][j]] += 1
i += 1
j += 1
ans += t
print(ans*2)
作者:About1263