KickStart 2020-Round-A python版解題

前言

第一次接觸kick start违帆,先刷了幾輪體驗(yàn)一下浙巫,好久沒有做類似的編程題目,不太會(huì)做了...
暫時(shí)使用Python編程前方,后續(xù)也會(huì)用C++再實(shí)現(xiàn)一遍狈醉。

RoundA 地址https://codingcompetitions.withgoogle.com/kickstart/round/

Round A

1. Allocation

有 n 套房子出售。買第一棟房子花了A_i美元惠险。你有一個(gè) B 美元的預(yù)算可以花苗傅。你最多能買多少套房子?
輸入
輸入的第一行給出了測(cè)試用例的數(shù)量班巩,接下來是 T,T 測(cè)試用例渣慕。每個(gè)測(cè)試用例都以包含兩個(gè)整數(shù) N 和 B 的單行開始。第二行包含 N 個(gè)整數(shù)抱慌。A_i逊桦,第i個(gè)房子的成本。

題解:分配問題抑进,將單價(jià)進(jìn)行升序排序强经,然后從小到大用B購(gòu)買即可。(注:kick start不提供輸入輸出處理寺渗,需要自己對(duì)輸入和輸出進(jìn)行標(biāo)準(zhǔn)化處理)

T=input()
for i in range(int(T)):
    _=input().split(' ')
    N=int(_[0])
    B=int(_[1])
    As=input().split(' ')
    As=[int(_) for _ in As]
    As.sort()
    res=0
    for a in As:
        if a <= B:
            res+=1
            B-=a
        if B<=0:
            break
    print('Case #{}: {}'.format(i+1,res)) 

2. Plates

有 N堆盤子匿情。每個(gè)堆包含 K個(gè) 盤兰迫。每個(gè)盤子都有一個(gè)正值,描述它看起來是多么美麗【娉疲現(xiàn)在需要P個(gè) 盤子做晚餐汁果。如果他想在一堆中拿一個(gè)盤子,他也必須在那堆中拿上面的所有盤子玲躯。挑選美麗值總和最大的P個(gè)盤子据德。
輸入
每個(gè)測(cè)試用例都以包含三個(gè)整數(shù) N,K 和 P 的一行開始跷车,然后是 N行棘利。第 i 行包含 K 個(gè)整數(shù),從上到下描述每一堆里盤子的美麗值姓赤。

題解:整個(gè)問題可以描述成下圖的情況赡译,將盤子進(jìn)行分配;從N*K中按照規(guī)則選取P個(gè)盤子不铆,可以用動(dòng)態(tài)規(guī)劃的方法來實(shí)現(xiàn)

按照動(dòng)態(tài)規(guī)劃的思路蝌焚,我們需要建立基本的動(dòng)態(tài)規(guī)劃公式,對(duì)應(yīng)dp[i][j]誓斥,dp[N][K]就是最后要的結(jié)果只洒。

分析過程如下
T=int(input())
for i in range(T):
    N,K,P=[int(_) for _ in input().split(' ')]
    Ns=[]
    res=0
    for _ in range(N):
        Ns.append([int(_) for _ in input().split(' ')])
    _sum=[]
    _sum.append([0 for _ in range(K)])
    for _ in Ns:
        _tmp=[]
        _tmp.append(0)
        for idx,x in enumerate(_):
            if not idx:
                _tmp.append(x)
            else:
                _tmp.append(x+_tmp[-1])
        _sum.append(_tmp)
    res=[[0 for _ in range(P+1)] for _ in range(N+1)]
    for n in range(1,N+1):
        for p in range(P+1):
            for x in range(0,min(K,p)+1):
                res[n][p]=max(res[n][p],_sum[n][x]+res[n-1][p-x])
        
    print('Case #{}: {}'.format(i+1,res[N][P]))

3. WorkOut

給定N個(gè)遞增的正整數(shù),然后向數(shù)組中插入K個(gè)正整數(shù)使得數(shù)組仍然遞增劳坑,同時(shí)達(dá)到數(shù)組相鄰元素差值最斜锨础;求插入后兩個(gè)相鄰元素差值的最大值是多少距芬。

題解:題目的意思可以用下面一張圖來表示涝开,通過插入K個(gè)值使得數(shù)組相鄰差值的最大值最小化

結(jié)果所需的最優(yōu)差值
d_{best}
必然出現(xiàn)在
1 ,max(Delta_i)
間,且滿足相應(yīng)的劃分總次數(shù)不超過K框仔,(若需要把區(qū)間長(zhǎng)度為
Delta_i
的間隔分成最優(yōu)差值
d_{best}
,需要
ceil(Delta_i/d_{best})-1
個(gè)值插入)舀武。

線性搜索最優(yōu)差值就可以得到目標(biāo)結(jié)果,但時(shí)間復(fù)雜度較高离斩,會(huì)超時(shí)银舱;因此可以嘗試二分搜索,從1 ,max(Delta_i)中找出最優(yōu)差值跛梗,檢驗(yàn)當(dāng)前差值是否都符合劃分次數(shù)的限制要求即可寻馏,時(shí)間復(fù)雜度明顯下降。

import math
T=int(input())

for t in range(T):
    N,K=[int(_) for _ in input().split(' ')]
    ts=[int(_) for _ in input().split(' ')] 
    delta=[]
    for i,_ in enumerate(ts):
        if not i:
            continue
        delta.append(_-ts[i-1])
    def check(t):
        _sum=[]
        for _ in delta:
            _sum.append(math.ceil(_/t)-1)
        return sum(_sum)<=K

    max_d=max(delta)
    left=1
    right=max_d
    _ans=0
    while left<=right:
        mid=(left+right)//2
        if check(mid):
            right=mid-1
            _ans=mid
        else:
            left=mid+1
 
    print('Case #{}: {}'.format(t+1,_ans))
             
 

4. Bundling

給定N個(gè)字符串核偿,把其分配到大小為K的多個(gè)組里(K能整除N)诚欠;每個(gè)串僅能劃分到某一個(gè)組里面,且這個(gè)組的得分就等于該組所有字符串的最長(zhǎng)公共前綴的長(zhǎng)度。求劃分后各組最大分?jǐn)?shù)和轰绵。

The score of a group is equal to the length of the longest prefix shared by all the strings in that group. For example:The group {RAINBOW, RANK, RANDOM, RANK} has a score of 2 (the longest prefix is 'RA').
The group {ALLOCATION, PLATE, WORKOUT, BUNDLING} has a score of 0 (the longest prefix is '').

題解 可以看出這個(gè)題與最長(zhǎng)公共前綴有關(guān)家乘,可以使用字典樹來輔助解題,將N個(gè)字符串用字典樹進(jìn)行表示藏澳,自根而下,每個(gè)節(jié)點(diǎn)對(duì)應(yīng)一個(gè)字符耀找,每個(gè)節(jié)點(diǎn)可以保存一個(gè)前綴重復(fù)數(shù)量翔悠,即有多少個(gè)字符串有相同的前綴(從根節(jié)點(diǎn)到當(dāng)前節(jié)點(diǎn)),字典樹的形式如下圖所示

同時(shí)野芒,這個(gè)題目還符合貪心算法的思想蓄愁,即計(jì)算最長(zhǎng)公共前綴對(duì)應(yīng)的分值就能得到最后的最大分值;公共前綴長(zhǎng)度為
x
狞悲,對(duì)應(yīng)重復(fù)的字符串為
l
撮抓,相應(yīng)分值計(jì)算為
x*(l//K)
,對(duì)字典樹摇锋,從最長(zhǎng)公共前綴節(jié)點(diǎn)往根節(jié)點(diǎn)進(jìn)行遍歷丹拯,減去已經(jīng)使用的
(l//K)*K
個(gè)字符串,再進(jìn)行相應(yīng)的分值計(jì)算荸恕,直至遍歷完整個(gè)字典樹乖酬,即可得到對(duì)該字典樹的所有字符串的最大得分。

我們?cè)诰唧w實(shí)現(xiàn)時(shí)融求,按照遞歸的思路實(shí)現(xiàn)了下面的公式咬像,在完整測(cè)試集上出現(xiàn)了遞歸超層的RuntimeError的錯(cuò)誤。

from collections import defaultdict
class Char_Tree():
    def __init__(self):
        self.root={}
        self.root.setdefault('num',0)
        self.end='#'
    
    def insert(self,word):
        node=self.root
        for char in word:
            node=node.setdefault(char,{})
            node.setdefault('num',0)
            node['num']+=1
        node[self.end]=None

T=int(input())
for t in range(T):
    N,K=[int(_) for _ in input().split(' ')]
    str_list=[]
    for _ in range(N):
        str_list.append(input())
    predix=[]
    ct=Char_Tree()
    for _ in str_list:
        ct.insert(_)
    def travel(tree,step,_sum,ans ):
        for _ in tree:
            if _=='num' or _=='#':
                continue
            if tree:
                s,ans=travel(tree[_],step+1,0,ans)
                _sum+=s
        #print('tree',tree)
        tmp=(tree['num']-_sum)/K
        if tmp:
            ans+= tmp*step
            _sum+=tmp*K
        return _sum,ans
    _,ans=travel(ct.root,0,0,0)
    print('Case #{}: {}'.format(t+1,ans))

繼而做了簡(jiǎn)單的修改吃度,在創(chuàng)建字典樹的同時(shí)計(jì)算得分值杭攻,這是一種很簡(jiǎn)單巧妙的方法庇勃,建樹的過程就是從根向下的過程,而得分與公共前綴長(zhǎng)度即節(jié)點(diǎn)的深度相對(duì)應(yīng)倒彰,因此,在添加節(jié)點(diǎn)的過程中就可以計(jì)算得分蔑赘,每個(gè)節(jié)點(diǎn)都做s//K的操作狸驳,多個(gè)節(jié)點(diǎn)合起來就對(duì)應(yīng)成上面提到的x*(l//K)的分?jǐn)?shù)。

from collections import defaultdict
class Char_Tree():
    def __init__(self,K):
        self.root={}
        self.root.setdefault('num',0)
        self.end='#'
        self._sum=0
        self.K=K
    
    def insert(self,word):
        node=self.root
        for char in word:
            if char in node:
                node=node[char]
                self._sum-=node['num']//self.K
                #node.setdefault('num',0)
                node['num']+=1
                self._sum+=node['num']//self.K
            else:
                node=node.setdefault(char,{})
                node.setdefault('num',1)
                self._sum+=1//self.K
            
            
        #node[self.end]=None

T=int(input())
for t in range(T):
    N,K=[int(_) for _ in input().split(' ')]
    str_list=[]
    for _ in range(N):
        str_list.append(input())
    predix=[]
    ct=Char_Tree(K)
    for _ in str_list:
        ct.insert(_)
    print('Case #{}: {}'.format(t+1,ct._sum))

END

本人簡(jiǎn)書所有文章均為原創(chuàng)缩赛,歡迎轉(zhuǎn)載耙箍,請(qǐng)注明文章出處: http://www.reibang.com/p/61876e60403d。百度和各類采集站皆不可信酥馍,搜索請(qǐng)謹(jǐn)慎鑒別辩昆。技術(shù)類文章一般都有時(shí)效性,本人習(xí)慣不定期對(duì)自己的博文進(jìn)行修正和更新旨袒,因此請(qǐng)?jiān)L問本人簡(jiǎn)書主頁(yè)查看最新信息http://www.reibang.com/u/40d14973d97c
汁针。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末术辐,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子施无,更是在濱河造成了極大的恐慌辉词,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件猾骡,死亡現(xiàn)場(chǎng)離奇詭異瑞躺,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)兴想,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門幢哨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人嫂便,你說我怎么就攤上這事捞镰。” “怎么了毙替?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵岸售,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我蔚龙,道長(zhǎng)冰评,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任木羹,我火速辦了婚禮甲雅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘坑填。我一直安慰自己抛人,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布脐瑰。 她就那樣靜靜地躺著妖枚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪苍在。 梳的紋絲不亂的頭發(fā)上绝页,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音寂恬,去河邊找鬼续誉。 笑死,一個(gè)胖子當(dāng)著我的面吹牛初肉,可吹牛的內(nèi)容都是我干的酷鸦。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼臼隔!你這毒婦竟也來了嘹裂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤摔握,失蹤者是張志新(化名)和其女友劉穎寄狼,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體氨淌,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡例嘱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了宁舰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡奢浑,死狀恐怖蛮艰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情雀彼,我是刑警寧澤壤蚜,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站徊哑,受9級(jí)特大地震影響袜刷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜莺丑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一著蟹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧梢莽,春花似錦萧豆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至轻局,卻和暖如春洪鸭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背仑扑。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工览爵, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人夫壁。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓拾枣,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子梅肤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容