蓝桥杯 算法训练 ALGO-945车厢 python解法

本文探讨了一个有趣的问题:如何通过最少的座位交换使火车上的隔间内至少有三名乘客。通过对不同乘客数量的隔间进行分析,提出了一种有效的算法解决方案。

资源限制

内存限制:256.0MB   C/C++时间限制:1.0s   Java时间限制:3.0s   Python时间限制:5.0s

问题描述

  寒假到了,同学们一同坐火车出游。一节列车有N个隔间,一个隔间可以容纳四个人,隔间都住满了,同学们买到的票并不在一起,有的隔间没有同学,有的隔间只有一个同学,有的有两个,有的三个,有的住满了同学。如果一个隔间少于三个同学,那他(们)就会觉得十分孤单。好在可以跟别的乘客商量换座来让同学们住到同一个隔间,但劝说别人换位置是一件比较麻烦的事情,请问最少交换多少次能够让所有有同学的隔间中都有不少于三个同学?

输入格式

  输入的第一行,包含一个正整数N,表示隔间的数量。
  输入的第二行N个0~4的数字,表示每个隔间有多少个同学。

输出格式

  一个整数,表示最少交换次数。如果无论如何交换都无法满足要求,则输出-1。

样例输入

5
1 2 2 4 3

样例输出

2

数据规模和约定

  1<=N<=1000000

解法:直接考虑各数字的数量,优先将1和2凑成3个,同时根据不同可能分别判断。

def cou(s):  # 使用函数对列表中1,2,3,4的数量进行计数
    if s in lis:  # count方法若数字在列表中不存在会报错,需要提前判断
        a = lis.count(s)
        return a
    else:
        return 0


def judge(a, b, c, d):
    # 直接考虑列表中各数字的数量,根据1和2的数量大小分为两类(把特判另算的话也可以分为三类)
    if b >= a:  # 当2的数量大于等于1时
        if b == a:  # 特判,当b=a时,最少次数为b次
            print(b)
        else:  # 当b>a时,考虑e的数量能否被3整除
            e = b - a
            if e % 3 == 0:  # 若能整除,则每三个2只需操作两次
                print(a + (e // 3 * 2))
            else:  # 若不能整除,则判断留下了2的数量为1或者2的情况
                if e % 3 == 1:  # 剩余2的数量为1个时
                    e -= 1
                    if c >= 1:  # 若4的数量大于等于1个,则只需再操作一次
                        print(a + (e // 3 * 2) + 1)
                    elif a + d + e // 3 >= 2:  # 若当前3的数量大于等于2个,则再操作两次
                        print(a + (e // 3 * 2) + 2)
                    else:  # 若上述情况不满足,则必定无法满足题意
                        print(-1)
                else:  # 剩余2的数量为2个时,不用考虑其他数字的数量,只需再操作两次即可
                    e -= 2
                    print(a + (e // 3 * 2) + 2)
    else:  # 当1的数量大于2时,直接考虑e的数量能否被3整除
        e = a - b
        if e % 3 == 0:  # 若能整除,则每三个1只需操作两次
            print(b + e // 3 * 2)
        else:
            if e % 3 == 1:  # 剩余1的数量为1个时
                e -= 1
                if b + e // 3 + d >= 1:  # 若当前3的数量大于等于1个,则再操作一次
                    print(b + e // 3 * 2 + 1)
                elif c >= 2:  # 若4的数量大于等于2个,则只需再操作两次
                    print(b + e // 3 * 2 + 2)
                else:  # 若上述情况不满足,则必定无法满足题意
                    print(-1)
            else:  # 剩余1的数量为2个时
                e -= 2
                if c >= 1 or b + e // 3 + d >= 2:  # 若当前4的数量大于等于1个或3的数量大于等于2个,都至少再操作两次
                    print(b + e // 3 * 2 + 2)
                else:  # 若上述情况不满足,则必定无法满足题意
                    print(-1)


n = int(input())
lis = list(map(int, input().split()))
s1, s2, s4, s3 = cou(1), cou(2), cou(4), cou(3)
judge(s1, s2, s4, s3)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值