蓝桥杯Python杂题《做题技巧二》

矩阵拼接 

矩形拼接2022年第十三届省赛,lanqiao0J题号2238(难度值★★★★)10分

【问题描述】

        已知 3 个矩形的大小依次是a_{1} \times b_{1}, a_{2} \times b_{2}和 a_{3} \times b_{3}。用这 3 个矩形能拼 出的所有多边形中, 边数最少可以是多少?

        :用3 \times 2的矩形(用 A 表示)、 4 \times 1的矩形 (用 BB 表示) 和2 \times 4的矩 形(用\mathrm{C} 表示)可以拼出如下 4 边形。

        :用3 \times 2 的矩形 (用 A 表示)、 3 \times 1的矩形(用 BB 表示) 和 1 \times 1的矩 形(用 \mathrm{C}表示)可以拼出如下 6 边形。

【输入格式】

输入包含多组数据。

第一行包含一个整数 T, 代表数据组数。

以下 T 行, 每行包含 6 个整数 a_{1}, b_{1}, a_{2}, b_{2}, a_{3}, b_{3}。 其中 a_{1}, b_{1}是第一个矩 形的边长,a_{2}, b_{2} 是第二个矩形的边长, a_{3}, b_{3}​ 是第三个矩形的边长。

输出格式

对于每组数据, 输出一个整数代表答案。

【样例输入】

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) 的示意。

给定点\left(d_{1}, p_{1}, q_{1}\right) 和点 \left(d_{2}, p_{2}, q_{2}\right), 请问他们之间最少走多少步可以到达?

输入格式

输入一行包含 6 个整数 d_{1}, p_{1}, q_{1}, d_{2}, p_{2}, q_{2​ 表示两个点的坐标, 相邻两个整数之间使用一个空格分隔。

输出格式

输出一行包含一个整数表示两点之间最少走多少步可以到达。

样例输入

0 5 3 2 3 2

样例输出

7

评测用例规模与约定

对于25% 的评测用例,p_{1}, p_{2} \leq 10^{3};

对于 50% 的评测用例, p_{1}, p_{2} \leq 10^{5};

对于 75% 的评测用例, p_{1}, p_{2} \leq 10^{7};

对于所有评测用例, 0 \leq d_{1}, d_{2} \leq 5,0 \leq q_{1}<p_{1} \leq 10^{9}, 0 \leq q_{2}<p_{2} \leq 10^{9}

【例题分析】

分析:蜂巢有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/

将下面的题号带入上面链接的“题号”中即可找到本题 。

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小叶pyか

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值