圆桌:满足客人空座需求,准备最少的椅子,合理安排客人入座圆桌

75 篇文章 0 订阅

CSDN周赛第30期第四题算法解析。


(本文获得CSDN质量评分【90】)

【学习的细节是欢悦的历程】


  自学并不是什么神秘的东西,一个人一辈子自学的时间总是比在学校学习的时间长,没有老师的时候总是比有老师的时候多。
            —— 华罗庚


等风来,不如追风去……


CSDN周赛第30期第四小题
圆 桌
(算——法——解——析)


本文质量分:

90
本文地址: https://blog.csdn.net/m0_57158496/article/details/129435473

CSDN质量分查询入口:http://www.csdn.net/qc


目 录


◆圆桌


1、题目描述


【CSDN周赛第30期第四题】

题目 4/4 (25 分)
题目名称:圆桌
时间限制:1000ms内存限制:256M

  有N个客人与足够多张的圆桌。主人安排每位客人坐在一个圆桌边,但是每位客人希望自己左右边上分别有一些空座位,不然会觉得害羞。注意,如果一个客人所在的圆桌只有他一个人,那么他左边的空座位数量就是他右边的空座位数量。 试问主人需要准备多少个座位,才能让每个客人舒适的坐下。

输入描述:
  第一行输入一个整数N,(1<=N<=10000),代表客人的数量 接下来N行,每行两个整数li与ri,(1<=i<=N,1<=li<=ri<=1000000000) 代表第i位客人希望左边有li个空座位,右边有ri个空座位。

输出描述:
  输出一个整数,代表主人需要准备的最少座位数量。

样例1
输入
3
1 1
1 1
1 1

输出
6

样例2
输入
4
1 2
2 1
3 5
5 3

输出
15

提示
【样例解释】3个人围成一桌,每人左右各一个空位置,一共3个空座位。一个共需要3+3=6座位。


2 、应考代码


应考答题截屏图
在这里插入图片描述

  应试时,我连题目都没有理清,所以写出了“不知所云”的代码。


回页目录

3、解题算法解析


3.1 算法分析

  首先,要分析哪些客人可以坐一个圆桌,从输入数组分拣出可以坐一桌的客人。再依同桌客人空座信息数组计算所用空座。所有圆桌的空座总数加上客人数,即为所要准备的椅子数。

如示例1:

输入
3
1 1
1 1
1 1

  三个客人左右空座相同,都是1,可以共坐一桌空座需3个,3+3=6,6即是所需准备的椅子总数。

输出
6

3.2 实现题目示例


统计分拣可以同桌的客人

    while lis: # 统计同桌客人。
        tem = [lis[0]]
        l, r = lis[0]
        lis.pop(0)
        
        for i in lis[:]: # 这里一定要遍历用切片复制lis[:],因为lis可能“动态”变短。
            li, ri = i

            if li == r:                
                tem.append(i)
                lis.remove(i)
                r = r


  同桌客人,前一个右边的空座即是后一个客人左边的空座,最后一个客人右边的空座即是第一个客人左边的空座。所以,同桌空座总数即为所有客人右边的空座和。

计算每张圆桌空座:用列表解析出每个客人右边的空座数,用sum()求和。


    for i in temp: # 遍历客人分桌列表,计算同桌客人共用空座。
        result += sum(j[1] for j in i)

代码运行效果
在这里插入图片描述
空座1、1、1 + 3人 = 6

在这里插入图片描述
空座(2、1 + 5、3) + 4人 = 15

  可以正确输出题目示例,看似完成了代码编写,代码实则是有缺陷的,我们换种输入试试:
在这里插入图片描述
在这里插入图片描述

  很显然,代码误把能挨个坐成一排,但不却不可以围坐一张圆桌的客人硬拉一起计算共用空座,得到错误的输出。

3.3 修正“同桌分拣”缺陷


  加入同桌分拣检验判定:从最后一个客人开始判定,不可以与首位客人相邻围坐,将该客人数组退回未分拣客人空座信息数组,循环“操作”,直到仅剩一个客人(客人独坐)。


        while len(tem) > 1:
            l_start, ri = tem[-1][1], tem[0][0]
            if ri == l_start:
                break # 客人空座链能首尾相接围坐一桌,退出检验循环。
            else: # 否则,把最后一位客人退回客人空座信息列表lis。
                lis.append(tem.pop())

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  经多组输入数据验证,代码可以正确“分桌”了。🤪


回页目录

3.3 客人左右不等空座的“迷茫”


  “注意,如果一个客人所在的圆桌只有他一个人,那么他左边的空座位数量就是他右边的空座位数量。”题目描述中的这句话就是说,任何空座需求的客人,如独围一桌,自成一圈,客人的左边也就是他自己的右边。示例1好理解,仍然是6 (每桌空座([1] × 3 + 3)。因为其左右空座会连在一起,不会违背“他左边的空座位数量就是他右边的空座位数量”。
  示例2,如分4桌坐,前两位客人的空座是2呢还是1呢?后二位是3还是5哩?


在这里插入图片描述

代码


        if len(i) == 1:
            result += max(i[0])
            continue

  于是我基于个人想法,当一个客人独坐一桌时,li = ri,我用max()取(li, ri)较大值来计算空座。如输入:3, [(1, 1), (3, 4), (5, 7)],三人都独坐一桌,空座1 + 4 + 7 = 12,12 + 3 = 15。

在这里插入图片描述

  但这样子的“操作”,是和题目描述
注意,如果一个客人所在的圆桌只有他一个人,那么他左边的空座位数量就是他右边的空座位数量。”不对付的。😣

  到底该怎么办?请有心的阅读者在评论区留言探讨。


回页目录

4、 我对题目描述的疑惑


对本题目描述中,我有两点疑虑:
  • “1<=li<=ri<=1000000000”条件限定

   样例2的输入,就不满足 li <= ri 啊!

  • “注意,如果一个客人所在的圆桌只有他一个人,那么他左边的空座位数量就是他右边的空座位数量。 ”

   对于这段描述,对于 li != ri 的客人需求,该如何让客人“舒适就坐”?


回页目录

  

5、完整源码

#!/sur/bin/nve python 
# coding: utf-8

'''

CSDN周赛第30期第04题:圆桌

'''

#04 圆桌


def table(n, lis):
    ''' 计算桌数和需准备座位数 '''
    result = 0 # 需求空座位数初值。
    temp = [] # 相同空座需求客人统计列表初始化。
    
    
    while lis: # 统计同桌客人。
        tem = [lis[0]]
        l, r = lis[0]
        lis.pop(0)
        
        for i in lis[:]: # 这里一定要遍历用切片复制lis[:],因为lis可能“动态”变短。
            li, ri = i

            if li == r:                
                tem.append(i)
                lis.remove(i)
                r = ri

        while len(tem) > 1:
            l_start, ri = tem[-1][1], tem[0][0]
            if ri == l_start:
                break # 客人空座链能首尾相接围坐一桌,退出检验循环。
            else: # 否则,把最后一位客人退回客人空座信息列表lis。
                lis.append(tem.pop())

        temp.append(tem)

    print(f"\n{'':~^50}\n客人分桌信息数组:\n{temp}\n{'':~^50}")
    
    for i in temp: # 遍历客人分桌列表,计算同桌客人共用空座。

        if len(i) == 1:
            result += max(i[0])
            continue

        result += sum(j[1] for j in i)

    return len(temp), result + n # 返回客人桌数和需准备的椅子总数(空座数+客人数)。


if __name__ == '__main__':
    n = int(input('\n输入:\n'))
    lis = [tuple(map(int, input().strip().split())) for i in range(n)]
    t = table(n, lis)
    print(f"\n输出:\n{t[1]}\n\n客人需坐{t[0]}桌,共要准备{t[1]}个椅子。")


回页首

__上一篇:__ re.findall获取CSDN博文阅读点赞收藏和评论实时数据(学用curl命令获取博文页面源码,学不会爬虫先手剥CSDN博文阅读点赞收藏和评论实时数据。)
__下一篇:__ 

我的HOT博:

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

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

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

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    打赏作者

    梦幻精灵_cq

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

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

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

    打赏作者

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

    抵扣说明:

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

    余额充值