Codility每周一课:P91.4 DwarfsRafting
P91.4 DwarfsRafting
Find out how many dwarfs can fit on a raft such that it's balanced when crossing a river.
-
P91.4 小矮人乘木筏
保持过河安全的前提下,木筏可以容纳的矮人的最大数量
矮人们正在新西兰的各地旅行。来到了克拉莎河,想要过河,但桥被暴风雨冲走了。幸运的是,有一艘木筏正在河上漂流。
木筏是方形的,有N排座位,编号从1到N。每排包含N个座位,用连续的字母(A、B、C等)标记。每个座位都有一个字符串标识,标识由座位的行号和列号组成;例如,座位标识为“9C”的表示第9行的第三个座位。
一些座位已经装载了木桶,一些座位已经被其他的矮人占据。这些矮人只能坐剩下的空位。渡船工人希望尽可能多地容纳矮人,但渡河时,木筏需要保持平衡。即必须满足以下条件:
- 木筏的前半部分和后半部分(根据座位排数)必须包含相同数量的矮人;
- 同样,筏板的左侧和右侧(就座椅立柱而言)必须包含相同数量的矮人。
- 木桶不用考虑,假设它们的重量可以忽略不计。
例如,尺寸为N=4的筏板如下图所示:
image棕色正方形为放了木桶的座位,已经被矮人占据的座位标为d。
木桶占据的座位以字符串S给出。已经被矮人占据的座位以字符串T给出。字符串中的座位之间用单个空格分隔,并且可以以任何顺序出现。例如在上图中,S="1B 1C 4B 1D 2A"和t="3B 2D"。 如下图中的绿色方块所示,木筏最多可容纳六个矮人:
image并且木筏可以保持平衡:左右两部分有相同数量的矮人(四个),前后两部分有相同数量的矮人(四个)。
编写函数:
def solution(N, S, T)
给定大小为N的木筏,和描述已经被木桶以及矮人占据的座位位置的字符串S,T。返回在保持木筏平衡的前提下,可以容纳的矮人们的数量。如果无论如何都不能保持木筏的平衡,则返回-1。例如,针对上面的示例,函数应该返回6。
假定:
- N是区间[2,26]内的偶数;
- 字符串S,T由有效的座位标识组成,标识之间用一个空格隔开;
- 每个座位标识在字符串中最多出现一次;
- S和T中不能同时出现同一个座位标识。
在解决方案中,关注正确性,性能不是评估的重点。
- 解题思路
给出最终木筏保持平衡,需要满足的条件:
- 左下、右上两部分中的矮人数必须是一样的,矮人包括已经在木筏上的矮人和即将被安排的矮人;
- 左上、右下两部分中的矮人数必须是一样的,矮人包括已经在木筏上的矮人和即将被安排的矮人;
首先根据字符串获得右上,右下,左上,左下,已经被木桶和矮人占据的座位。计算出每一部分已经有的矮人数和剩余的座位。然后判断是否有保持平衡的可能性,对于处于对角部分的2部分而言,只有一部分的矮人数和剩余的座位数之和不小于另一部分已有的矮人的数,才有可能保持平衡。因此这2部分最终可以承载的矮人的数,就是这2部分各自的矮人数和剩余的座位数之和的最小值,最终计算出每一部分需要新接纳多少矮人即可得到最终的答案。
- Python3代码
# -*- coding:utf-8 -*-
# &Author AnFany
# Lesson 91:Tasks from Indeed Prime 2016 challenge
# P 91.4 DwarfsRafting
def encode_str(seat_str, n):
"""
根据座位字符串,返回座位行数为键,座位列号为值的字典
:param seat_str: 存放座位信息的字符串
:param n: 木筏上座位的行数和列数
:return: 字典
"""
# 将木筏分为左上,右上,左下,右下四部分,这四部分分别定义为0, 1, 2, 3
seat_dict = {i: 0 for i in range(4)}
if not seat_str: # 字符串为空
return seat_dict
else:
seat_dict = {i: 0 for i in range(4)}
str_list = seat_str.split(' ') # 间隔一个空格
for i in str_list:
if len(i) == 2: # 行号可能是2位数
row, column = i
else:
row, column = i[:2], i[2]
if int(row) <= n / 2: # 是上半部分的
if ord(column) - ord('A') < n / 2: # 左上
seat_dict[0] += 1
else: # 右上
seat_dict[1] += 1
else: # 是下半部分的
if ord(column) - ord('A') < n / 2: # 左下
seat_dict[2] += 1
else: # 右下
seat_dict[3] += 1
return seat_dict
def solution(N, S, T):
"""
根据已经站的座位,使得木筏各个部分保持平衡的前提下可以容纳的最多人数
:param N: 偶数,代表座位的行数和列数
:param S: 承载木桶的座位
:param T: 承载其他矮人的座位
:return: 新容纳矮人的最大人数
"""
barrels_dict = encode_str(S, N) # 木桶占据的座位
pepole_dict = encode_str(T, N) # 矮人们已经占据的座位
# 每个部分的座位总数为
all_seats = (N // 2) ** 2
# 计算每个部分已有矮人的数量和剩余空位的数量确定容纳的人数
part_dict = {k: [pepole_dict[k], all_seats-pepole_dict[k]-barrels_dict[k]] for k in pepole_dict}
# 左上和右下部分
sum_left_up = sum(part_dict[0])
sum_right_down = sum(part_dict[3])
# 当一部分的已有矮人的数量和剩余空位的数量之和不小于另一部分的已有矮人的数量,才可以平衡
if sum_left_up >= part_dict[3][0] and sum_right_down >= part_dict[0][0]:
left_up_right_down = min(sum_left_up, sum_right_down) # 左上和右下部分每一部分最多可以承载的人数
# 计算左上和右下部分,每一部分可以新承载矮人的数
new_left_up_right_down = 2 * left_up_right_down - part_dict[0][0] - part_dict[3][0]
else:
return -1
# 左下和右上部分
sum_left_down = sum(part_dict[2])
sum_right_up = sum(part_dict[1])
# 当一部分的已有矮人的数量和剩余空位的数量之和不小于另一部分的已有矮人的数量,才可以平衡
if sum_left_down >= part_dict[1][0] and sum_right_up >= part_dict[2][0]:
left_down_right_up = min(sum_left_down, sum_right_up) # 左下和右上部分每一部分最多可以承载的人数
# 计算左下和右上部分,每一部分可以新承载矮人的数
new_left_down_right_up = 2 * left_down_right_up - part_dict[1][0] - part_dict[2][0]
else:
return -1
return new_left_up_right_down + new_left_down_right_up
- 结果
点击获得更多编程练习题。欢迎Follow,感谢Star!!! 扫描关注微信公众号pythonfan,获取更多。
image image