矩阵拼接
矩形拼接2022年第十三届省赛,lanqiao0J题号2238(难度值★★★★)10分
【问题描述】
已知 3 个矩形的大小依次是
和
。用这 3 个矩形能拼 出的所有多边形中, 边数最少可以是多少?
例:用
的矩形(用 A 表示)、
的矩形 (用 BB 表示) 和
的矩 形(用
表示)可以拼出如下 4 边形。
例:用
的矩形 (用 A 表示)、
的矩形(用 BB 表示) 和
的矩 形(用
表示)可以拼出如下 6 边形。
【输入格式】
输入包含多组数据。
第一行包含一个整数 T, 代表数据组数。
以下 T 行, 每行包含 6 个整数
。 其中
是第一个矩 形的边长,
是第二个矩形的边长,
是第三个矩形的边长。
输出格式
对于每组数据, 输出一个整数代表答案。
【样例输入】
2
2 3 4 1 2 4
1 2 3 4 5 6
【样例输出】4
6【评测用例规模与约定】T组测试,每个测试给出6个数据,表示3个矩阵。1 ≤T ≤1000,1 ≤al,b1, a2,b2,a3,b3≤100。
【例题分析】
本题是一道纯粹的构造题,思维简单,但是代码比较繁琐细致,考核编码能力
3个矩形摆在一起,可能有几个边?在纸上手画观察;
- 3个矩形完全不能匹配:8边形
- 能完全匹配成一个新矩形:4边形
- 其他情况:6边形
本题只有3个矩形,3个矩形做任意排列(3!=6),每个矩形有横竖两种摆法(2×2×2=8),共48种情况。
T = 1000组测试,总计算量是1000×48,计算量很小不会超时,所以简单地用暴力法组合出所有情况,取最小值即可。
情况一:三个矩形有一边相等。(完全匹配:4边)
情况二:三个矩形中有前两个矩形的边等于第三个矩形的边,而且前两个矩形的另一条边相等。(完全匹配:4边)
情况三: 三个矩形中有前两个矩形的边等于第三个矩形的边,而且前两个矩形的另一条边不相等。(部分匹配:6边)
情况四:其他情况(完全不匹配:8边)
【代码演示】
# 完全匹配条件:三个矩形中有前两个矩形的边等于第三个矩形的边,而且前两个矩形的另一条边相等
def check1(x1,x2,x3): # 完全匹配:四边形
if x1>=x2 and x1>=x3:
if x1==x2+x3 and a[2]+a[3]-x2==a[4]+a[5]-x3:return True
if x2>=x1 and x2>=x3:
if x2==x1+x3 and a[0]+a[1]-x1==a[4]+a[5]-x3:return True
if x3>=x1 and x3>=x2:
if x3==x1+x2 and a[0]+a[1]-x1==a[2]+a[3]-x2:return True
return False
def check2( x1,x2,x3): # 部分匹配:六边形
if x1>=x2 and x1>=x3:
if x1==x2+x3:return True # 这里不需要判断前两个矩形另一边不相等,因为check1()函数已经选出了相等的,所以剩下的都是不相等的
if x2>=x1 and x2>=x3:
if x2==x1+x3:return True
if x3>=x1 and x3>=x2:
if x3==x1+x2:
return True
return False
T = int( input()) # 读取T组测试
for t in range(T):
a=list(map(int,input().split())) # 读取三个矩形的长和宽
ans=8 # 最大的边数(最差的结果)
for i in range(0,2): # 第1个矩形:横竖两种摆法a[0]和[1]
for j in range( 2,4): # 第2个矩形:横竖两种摆法a[2]和a[3]
for k in range(4,6): # 第3个矩形:横竖两种摆法a[4]和a[5]
x1,x2,x3 = a[i],a[j],a[k] # x1,x2,x3是三个矩形的一边,6种组合
if x1==x2 and x2==x3: # 情况一:三个矩形有一边相等
ans = min( ans,4)
if check1( x1,x2,x3):
ans = min( ans,4)
if x1==x2 or x1==x3 or x2==x3:
ans = min(ans,6)
if check2(x1,x2,x3):
ans = min( ans,6)
print(ans)
蜂巢
蜂巢2022年第十三届省赛,lanqiao0J题号2134(难度值★★★)
【问题描述】
蜂巢由大量的六边形拼接而成, 定义蜂巢中的方向为: 0 表示正西方向, 1 表示西偏北 60°,2 表示东偏北 60°,3 表示正东, 4 表示东偏南60°,5 表示西 偏南60°。
对于给定的一点 O, 我们以 O 为原点定义坐标系, 如果一只蜜蜂 由 O 点 先向 d 方向走 p 步再向(d+2)mod6 方向 ( d 的顺时针 120° 方向) 走 q 步到达, 则这个点的坐标定义为 (d,p,q) 。在蜂窝中, 一个点的坐标可能有多种。(mod:取模运算符(可以默认为取余操作))
下图给出了点 B(0,5,3) 和点 C(2,3,2) 的示意。
给定点
和点
, 请问他们之间最少走多少步可以到达?
输入格式
输入一行包含 6 个整数
表示两个点的坐标, 相邻两个整数之间使用一个空格分隔。
输出格式
输出一行包含一个整数表示两点之间最少走多少步可以到达。
样例输入
0 5 3 2 3 2
样例输出
7
评测用例规模与约定
对于25% 的评测用例,
;
对于 50% 的评测用例,
;
对于 75% 的评测用例,
;
对于所有评测用例,
【例题分析】
分析:蜂巢有6个方向,看起来复杂,实际上走步非常简单。例如样例中从B走到C,C在B的右下方,B只要一直向右向下走,且不超过C的行和列,不管怎么走,一定能以最小步数走到C。
本题是一道构造题,考点有两个:坐标转换、距离计算。
本题的难点是对坐标的处理。如果是简单的直角坐标系,很容易计算。本题是六角形的蜂巢,每个蜂巢的中心点是否能转为直角坐标?
把蜂巢的关系用直角坐标表示:
中心点O,对应的6个蜂巢的坐标分别为(-2,0)、(-1,1)、(1,1)、(2,0)、(1, -1)、(-1,-1)。
先计算得到起点坐标(x 1, y1)、终点坐标(x2,y2)。
如何计算起点到终点的步数?由于蜂巢的坐标比较奇怪,不能直接用“曼哈顿距离”计算。下面给出一个简单巧妙的方法。
坐标之差的绝对值dx = |x1-x2l,dy = ly1-y2|,有以下结论:
(1)若dx ≥ dy,那么最少步数是(dx+dy)//2,即先横着走,再斜着走
(2)若dx <dy,一直斜着走就行,最少步数是dy。
【代码演示】
# 六个方向:[0]正西、[1]西偏北、[2]东偏北.....
xdir = [-2,-1,1,2, 1,-1]
ydir = [ 0, 1,1,0,-1,-1]
# 用于将两个点的坐标转换为直角坐标
def walk(d,q,x,y):
x += xdir[d]*q
y += ydir[d]*q
return x,y
d1,p1,q1,d2,p2,q2 = map( int,input( ).split()) # 读入两个点的坐标
# 处理坐标:把两个点的坐标转换为直角坐标
x1,y1 = walk(d1,p1,0,0) # 第一步:从原点先向d方向走p步到(x1,y1)
x1,y1 = walk((d1 +2)%6,q1,x1,y1) # 第二步:从(x1,y1)x向(d+2)mod6方向走q步
x2,y2 = walk(d2,p2,0,0)
x2,y2 = walk((d2 + 2)% 6,q2,x2,y2)
dx,dy = abs(x1 - x2),abs(y1 - y2) #
if dx >= dy:
print(( dx+dy )//2) # 先横走,再斜着走
else:
print(dy) # 一直斜着走
总结:
- 杂题没有用到复杂算法,)不懂数据结构和算法的初学者也能做题目可难可易,考核参赛者的思维和编码能力
- 杂题在蓝桥杯和其他算法竞赛中,都是常见且必不可少的题型
练习题
https://www.lanqiao.cn/problems/题号/learning/
将下面的题号带入上面链接的“题号”中即可找到本题 。