Codility每周一课:P91.4 DwarfsRafting

0.png

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行的第三个座位。

一些座位已经装载了木桶,一些座位已经被其他的矮人占据。这些矮人只能坐剩下的空位。渡船工人希望尽可能多地容纳矮人,但渡河时,木筏需要保持平衡。即必须满足以下条件:

  1. 木筏的前半部分和后半部分(根据座位排数)必须包含相同数量的矮人;
  2. 同样,筏板的左侧和右侧(就座椅立柱而言)必须包含相同数量的矮人。
  3. 木桶不用考虑,假设它们的重量可以忽略不计。

例如,尺寸为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。

假定:

  1. N是区间[2,26]内的偶数;
  2. 字符串S,T由有效的座位标识组成,标识之间用一个空格隔开;
  3. 每个座位标识在字符串中最多出现一次;
  4. 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
  • 结果
image

点击获得更多编程练习题。欢迎Follow,感谢Star!!! 扫描关注微信公众号pythonfan,获取更多。

image
image
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容

  • ORA-00001: 违反唯一约束条件 (.) 错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常。 O...
    我想起个好名字阅读 5,308评论 0 9
  • 相较于几乎没有文字描述的图画绘本,对于孩子来说,《不一样的卡梅拉》应属于篇幅较长、情节曲折的故事书。在我看...
    supermommy阅读 985评论 0 2
  • 罗莎出院了,一切都恢复了正常,只是我还在休假,在家照顾罗莎。 腿部功能训练乏善可陈,每天不再硬数次数,术后整整一周...
    林夕枫起阅读 180评论 0 0
  • 01 你喜欢大城市的繁华,我喜欢小城市的安逸; 你在小城,甘为平淡,悠然自得,我在大城,宁为梦想,奋不顾身。 ...
    欧小爱阅读 208评论 0 0
  • 以前工作的单位中,老板开会经常说得云山雾罩,这山跑那山去,通常新来的人要好久才能适应,才能明白他在讲什么,我们呆得...
    太后老三阅读 407评论 0 2