算法题笔记(python实现)

  • 做完签到题就是胜利系列

ACM输入输出

  • 基本输入:
    使用 input() 函数可以从标准输入读取一行,然后可以使用 split() 分割字符串并配合 map() 函数转换类型。
# 读取单个整数
n = int(input())

# 读取一行中的多个整数
a, b, c = map(int, input().split())

# 读取一行中的整数列表
numbers = list(map(int, input().split()))
  • 读取多行输入:
    当你需要读取多行输入时,可以使用循环。
# 读取n行输入,每行一个整数
n = int(input())
array = [int(input()) for _ in range(n)]

# 读取n行输入,每行多个整数
n = int(input())
array_of_tuples = [tuple(map(int, input().split())) for _ in range(n)]
  • 读取未知数量的输入行:
    当你不知道有多少行输入时,可以使用 try-except 块来处理 EOFError。
# 持续读取每行直到输入结束
try:
    while True:
        numbers = list(map(int, input().split()))
        # 处理numbers
except EOFError:
    pass
  • 基本输出:
    使用 print() 函数来输出结果。print() 默认在输出内容的末尾添加换行符。
# 输出单个变量
print(result)

# 输出多个变量(默认以空格分隔)
print(a, b, c)

# 输出不换行
print(result, end="")
  • 输出列表或序列:
    如果你需要输出一个列表或序列中的元素,可以使用 join() 方法。
# 输出列表中的整数,以空格分隔
print(" ".join(map(str, list_of_integers)))

1.淘汰分数

某比赛已经进入了淘汰赛阶段,已知共有n名选手参与了此阶段比赛,他们的得分分别是a_1,a_2….a_n,小美作为比赛的裁判希望设定一个分数线m,使得所有分数大于m的选手晋级,其他人淘汰。

但是为了保护粉丝脆弱的心脏,小美希望晋级和淘汰的人数均在[x,y]之间。

显然这个m有可能是不存在的,也有可能存在多个m,如果不存在,请你输出-1,如果存在多个,请你输出符合条件的最低的分数线。

  • 输入描述:
    输入第一行仅包含三个正整数n,x,y,分别表示参赛的人数和晋级淘汰人数区间。(1<=n<=50000,1<=x,y<=n)
    输入第二行包含n个整数,中间用空格隔开,表示从1号选手到n号选手的成绩。(1<=|a_i|<=1000)
  • 输出描述:
    输出仅包含一个整数,如果不存在这样的m,则输出-1,否则输出符合条件的最小的值。
  • 输入例子:
    6 2 3
    1 2 3 4 5 6
  • 输出例子:
    3
def lowestScore(n, x, y, scores):
   	sortedScores = sorted(scores)
   	# 最低分数线初始化为-1
    lowest = -1
    for i in range(n):
    	#遍历分数列表 设置初始淘汰人数为1,通过人数为n-1
        ifail = i + 1
        ipass = n - ifail
        if x <= ifail <= y and x <= ipass <= y:
        	#满足条件后,输出此时的分数线即为最低分数线
            lowest = sortedScores[i]
            break
    return lowest
# 读取输入数据 map将输入的字符串转化为整数
n, x, y = map(int, input().split())
scores = list(map(int, input().split()))
# 输出结果
print(lowestScore(n, x, y, scores))

2.正则序列

我们称一个长度为n的序列为正则序列,当且仅当该序列是一个由1~n组成的排列,即该序列由n个正整数组成,取值在[1,n]范围,且不存在重复的数,同时正则序列不要求排序

有一天小团得到了一个长度为n的任意序列s,他需要在有限次操作内,将这个序列变成一个正则序列,每次操作他可以任选序列中的一个数字,并将该数字加一或者减一。

请问他最少用多少次操作可以把这个序列变成正则序列?

  • 输入描述:
    输入第一行仅包含一个正整数n,表示任意序列的长度。(1<=n<=20000)
    输入第二行包含n个整数,表示给出的序列,每个数的绝对值都小于10000。

  • 输出描述:
    输出仅包含一个整数,表示最少的操作数量。

  • 输入例子:
    5
    -1 2 3 10 100

  • 输出例子:
    103

def regularTransfer(n, a):
	#直接排序后计算当前序列与目标序列的差值总和
    a = sorted(a)
    sum = 0
    for i in range(n):
        sum += abs(a[i] - i - 1)
    return sum

n = int(input())
a = list(map(int, input().split()))
print(regularTransfer(n, a))

1.糕点

小团的蛋糕铺长期霸占着美团APP中“蛋糕奶茶”栏目的首位,因此总会吸引各路食客前来探店。
小团一天最多可以烤n个蛋糕,每个蛋糕有一个正整数的重量。
早上,糕点铺已经做好了m个蛋糕。
现在,有一个顾客要来买两个蛋糕,他希望买这一天糕点铺烤好的最重的和最轻的蛋糕,并且希望这两个蛋糕的重量恰好为a和b。剩余的n-m个蛋糕可以现烤,请问小团能否满足他的要求?

  • 输入描述:
    输入包含多组数据,每组数据两行。
    每组数据的第一行包含4个整数,n,m,a,b,空格隔开。这里不保证a和b的大小关系。
    接下来一行m个数,空格隔开,代表烤好的蛋糕重量

  • 输出描述:
    对于每一组数据,如果可以办到顾客的要求,输出YES,否则输出NO

  • 输入例子:
    4 2 2 4
    3 3
    4 2 2 4
    1 1
    4 2 2 4
    5 5
    4 2 4 2
    2 4
    2 2 2 4
    3 3
    3 2 2 4
    3 3
    3 2 2 4
    3 3

  • 输出例子:
    YES
    NO
    NO
    YES
    NO
    NO
    NO

def fun(n, m, a, b, cakes):
    if a in cakes and b in cakes:
        #刚好满足
        return 'YES'
    elif n - m == 0:
        #不可以再烤
        return 'NO'
    elif min(cakes) <= b <= max(cakes) and min(cakes) <= a <= max(cakes):
        #两个蛋糕均在范围内但不是最大/最小
        return 'NO'
    elif (max(cakes) < a and max(cakes) < b) or (min(cakes) > a and min(cakes) > b): 
        #两个蛋糕大于当前最大值或小于当前最小值
        return 'NO'
    elif ((a > max(cakes) and b < min(cakes)) or (b > max(cakes) and a < min(cakes))) and n - m < 2: 
        #需要再烤两个但剩余数量不够
        return 'NO'
    else: 
    	#还有一种情况是需要再烤一个,此时已经排除剩余数量为0的情况
        return 'YES'

try:
    while True:
        n, m, a, b = map(int, input().split())
        cakes = list(map(int, input().split()))
        print(fun(n, m, a, b, cakes))
except EOFError:
    pass

2.晋级人数

小团是某综艺节目的策划,他为某个游戏环节设计了一种晋级规则,已知在这个游戏环节中每个人最后都会得到一个分数score_i,显而易见的是,游戏很有可能出现同分的情况,小团计划该环节晋级人数为x人,则将所有人的分数从高到低排序,所有分数大于等于第x个人的分数且得分不为0的人都可以晋级。

请你求出本环节的实际晋级人数。显然这个数字可能是0,如果所有人的得分都是0,则没有人满足晋级条件。

  • 输入描述:
    输入第一行包含两个正整数n和x,分别表示参加本环节的人数,和小团指定的x。
    输入第二行包含n个整数,每个整数表示一位选手的得分。

  • 输出描述:
    输出仅包含一个整数,表示实际晋级人数。

  • 输入例子:
    5 4
    0 0 2 3 4

  • 输出例子:
    3

def passPerson(n, x, scores):
    sum = 0
    scores = sorted(scores, reverse=True)#降序排序
    if max(scores) == 0:
        return 0
    for i in range(n):
        if scores[i] >= scores[x-1] and scores[i] != 0:
            sum += 1
    return sum
n, x = map(int, input().split())
scores = list(map(int, input().split()))
print(passPerson(n, x, scores))

1.小美的书架

小美的书架上有很多书。小美是个爱读书的新时代好青年。

小团虽然也喜欢看书,但小团大多数时候都更喜欢来小美家蹭书读。

这就导致小美的书架上很多书都会被小团借走。

小美很烦这一点,就想出了一个招数,小美的书架是一行一行的,他会对一些行加锁,这样小团就借不走了。

现在小团想要借书,请你帮忙看看小团能不能借到书,如果可以借到的话在哪一行书架上有这本书。

为了简单起见,每本书将用一个正整数进行编号,小美的书架一共有N行。

  • 输入描述:
    第一行两个正整数N,M,Q,表示小美书架有N行编号1到N,书本编号从1到M,接下来有Q个操作
    接下来Q行,每行是下列操作中的一种:
    1 x y : x是书本的编号,y是书架的行编号,代表小美将编号为x的书本放置到y行上。若该书本在小团手上则放置无效,若原来该书在书架上且原行上锁则放置无效,若该书被放置到一个锁了的行上则放置无效。
    2 y : y是书架的行编号,代表小美将行编号为y的书架加锁,对已经上锁的书架行该操作无效。
    3 y : y是书架的行编号,代表小美将行编号为y的书架锁去掉,对无锁的书架行该操作无效。
    4 x : x是书本的编号,代表小团想借编号为x的书本,对该操作若可以借到输出一行正整数在哪一行,借不到输出一行-1
    5 x : x是书本的编号,代表小团还回来编号为x的书本。若该书本不在小团手上该操作无效。

  • 输出描述:
    对于每个操作4,若可以借到输出一行正整数在哪一行,借不到输出一行-1

  • 输入例子:
    5 5 10
    1 1 4
    1 2 3
    1 3 1
    2 1
    4 1
    5 2
    4 3
    4 5
    3 1
    4 2

  • 输出例子:
    4
    -1
    -1
    3

class Shelf:
    def __init__(self):
        self.lock = False
        self.book = set()


class Book:
    def __init__(self):
        self.num = 0
        self.line = 0


if __name__ == "__main__":
    n, m, q = map(int, input().split())
    shelf = [Shelf() for _ in range(10000)]
    book = [Book() for _ in range(10000)]

    for _ in range(q):
        inputs = list(map(int, input().split()))
        op = inputs[0]
        if op == 1:
            x, y = inputs[1], inputs[2]
            if book[x].num or shelf[book[x].line].lock or shelf[y].lock:
                continue
            shelf[y].book.add(x)
            book[x].line = y
        elif op == 2:
            y = inputs[1]
            shelf[y].lock = True
        elif op == 3:
            y = inputs[1]
            shelf[y].lock = False
        elif op == 4:
            x = inputs[1]
            if book[x].num or shelf[book[x].line].lock or book[x].line == 0:
                print(-1)
            else:
                print(book[x].line)
                shelf[book[x].line].book.remove(x)
                book[x].num = 1
                book[x].line = 0
        else:
            x = inputs[1]
            if book[x].num == 0:
                continue
            book[x].num = 0
            book[x].line = 0

2.偏爱字母

小美喜欢字母E,讨厌字母F。在小美生日时,小团送了小美一个仅包含字母E和F的字符串,小美想从中选出一个包含字母E数量与字母F数量之差最大的子串。

*子串:从字符串前面连续删去若干个字符,从后面连续删去若干个字符剩下的字符串(也可以一个都不删),例如abcab是fabcab的子串,而不是abcad的子串。我们将空串看作所有字符串的子串。

  • 输入描述:
    第一行一个正整数n表示字符串的长度。
    第二行长度为n,且仅包含大写字母’E’,’F’的字符串(不含引号)

  • 输出描述:
    输出一个整数,表示最大的差值

  • 输入例子:
    5
    EFEEF

  • 输出例子:
    2
    例子说明:
    选择子串EE,此时有2个E,0个F,有最大差值2-0=2
    另外,选择子串EFEE也可以达到最大差值。

def chooseSubStr(n, str):
    # 初始化当前差值和最大差值
    current_diff = max_diff = 0
    # 遍历字符串
    for char in str:
        # 如果字符是'E',差值加1,否则差值减1
        current_diff += 1 if char == 'E' else -1        
        # 如果当前差值小于0,重置差值为0
        if current_diff < 0:
            current_diff = 0
        # 更新最大差值
        max_diff = max(max_diff, current_diff)
    print(max_diff)

n = int(input())
str = input()
chooseSubStr(n, str)

3.搭配出售

服装店新进了a条领带,b条裤子,c个帽子,d件衬衫,现在要把这些搭配起来售卖。有三种搭配方式,一条领带和一件衬衫,一条裤子和一件衬衫,一个帽子和一件衬衫。卖出一套领带加衬衫可以得到e元,卖出一套裤子加衬衫可以得到f元,卖出一套帽子加衬衫可以得到g元。现在你需要输出最大的获利方式

  • 输入:一行7个整数分别表示a,b,c,d,e,f,g。
  • 输出:最大利润
  • 输入例子:
    2 3 4 5 6 7 8
    输出例子:
    39
    例子说明:
    4个帽子加4件衬衫获利32元,1条裤子加1件衬衫获利7元,一共得到39元。
# 输入处理
a, b, c, d, e, f, g = map(int, input().split())
# 搭配方式和利润
combinations = [
    ('tie', a, e),
    ('pants', b, f),
    ('hat', c, g)
]
# 根据利润大小排序搭配方式
combinations.sort(key=lambda x: x[2], reverse=True)
# 计算最大获利
max_profit = 0
for _, count, profit in combinations:
    # 可以搭配的数量由衬衫数量和当前物品数量决定
    number_of_sets = min(d, count)    
    # 更新最大获利
    max_profit += number_of_sets * profit    
    # 减去已经使用的衬衫数量
    d -= number_of_sets
    # 如果衬衫已经用完,退出循环
    if d == 0:
        break
# 输出最大获利
print(max_profit)
  • 27
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值