python解题_KickStart 2020-Round-A python版解题

前言

第一次接触kick start,先刷了几轮体验一下,好久没有做类似的编程题目,不太会做了...

暂时使用Python编程,后续也会用C++再实现一遍。

Round A

1. Allocation

有 n 套房子出售。买第一栋房子花了

math?formula=A_i美元。你有一个 B 美元的预算可以花。你最多能买多少套房子?

输入

输入的第一行给出了测试用例的数量,接下来是 T,T 测试用例。每个测试用例都以包含两个整数 N 和 B 的单行开始。第二行包含 N 个整数。

math?formula=A_i,第i个房子的成本。

题解:分配问题,将单价进行升序排序,然后从小到大用B购买即可。(注:kick start不提供输入输出处理,需要自己对输入和输出进行标准化处理)

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堆盘子。每个堆包含 K个 盘。每个盘子都有一个正值,描述它看起来是多么美丽。现在需要P个 盘子做晚餐。如果他想在一堆中拿一个盘子,他也必须在那堆中拿上面的所有盘子。挑选美丽值总和最大的P个盘子。

输入

每个测试用例都以包含三个整数 N,K 和 P 的一行开始,然后是 N行。第 i 行包含 K 个整数,从上到下描述每一堆里盘子的美丽值。

题解:整个问题可以描述成下图的情况,将盘子进行分配;从N*K中按照规则选取P个盘子,可以用动态规划的方法来实现

61876e60403d

按照动态规划的思路,我们需要建立基本的动态规划公式,对应dp[i][j],dp[N][K]就是最后要的结果。

61876e60403d

分析过程如下

61876e60403d

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个递增的正整数,然后向数组中插入K个正整数使得数组仍然递增,同时达到数组相邻元素差值最小;求插入后两个相邻元素差值的最大值是多少。

题解:题目的意思可以用下面一张图来表示,通过插入K个值使得数组相邻差值的最大值最小化

61876e60403d结果所需的最优差值

math?formula=d_%7Bbest%7D必然出现在

math?formula=1%20%2Cmax(Delta_i)间,且满足相应的划分总次数不超过K,(若需要把区间长度为

math?formula=Delta_i的间隔分成最优差值

math?formula=d_%7Bbest%7D,需要

math?formula=ceil(Delta_i%2Fd_%7Bbest%7D)-1个值插入)。

线性搜索最优差值就可以得到目标结果,但时间复杂度较高,会超时;因此可以尝试二分搜索,从

math?formula=1%20%2Cmax(Delta_i)中找出最优差值,检验当前差值是否都符合划分次数的限制要求即可,时间复杂度明显下降。

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个字符串,把其分配到大小为K的多个组里(K能整除N);每个串仅能划分到某一个组里面,且这个组的得分就等于该组所有字符串的最长公共前缀的长度。求划分后各组最大分数和。

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 '').

61876e60403d

题解 可以看出这个题与最长公共前缀有关,可以使用字典树来辅助解题,将N个字符串用字典树进行表示,自根而下,每个节点对应一个字符,每个节点可以保存一个前缀重复数量,即有多少个字符串有相同的前缀(从根节点到当前节点),字典树的形式如下图所示

61876e60403d同时,这个题目还符合贪心算法的思想,即计算最长公共前缀对应的分值就能得到最后的最大分值;公共前缀长度为

math?formula=x,对应重复的字符串为

math?formula=l,相应分值计算为

math?formula=x*(l%2F%2FK),对字典树,从最长公共前缀节点往根节点进行遍历,减去已经使用的

math?formula=(l%2F%2FK)*K个字符串,再进行相应的分值计算,直至遍历完整个字典树,即可得到对该字典树的所有字符串的最大得分。

我们在具体实现时,按照递归的思路实现了下面的公式,在完整测试集上出现了递归超层的RuntimeError的错误。

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))

继而做了简单的修改,在创建字典树的同时计算得分值,这是一种很简单巧妙的方法,建树的过程就是从根向下的过程,而得分与公共前缀长度即节点的深度相对应,因此,在添加节点的过程中就可以计算得分,每个节点都做

math?formula=s%2F%2FK的操作,多个节点合起来就对应成上面提到的

math?formula=x*(l%2F%2FK)的分数。

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

本人简书所有文章均为原创,欢迎转载,请注明文章出处: https://i-blog.csdnimg.cn/blog_migrate/0c520944e953d3ca855229a5e2e6bdf0.png。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问本人简书主页查看最新信息https://www.jianshu.com/u/40d14973d97c

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python3-kickstart是一个用于快速启动Python 3项目的工具。它提供了一系列的命令和模板,帮助开发者在短时间内建立稳定可用的Python项目。 Python3-kickstart的主要功能包括: 1. 创建虚拟环境:它允许用户在项目目录中创建一个独立的Python虚拟环境,以避免项目之间的依赖冲突。 2. 安装依赖:它可以自动安装项目所需的依赖库,通过读项目的requirements.txt文件,节省了手动安装每个依赖库的步骤。 3. 生成配置文件:它提供了一个命令来生成常见的配置文件,如settings.py或config.py。这些配置文件包含了项目中的常用设置,例如数据库配置,日志记录等。 4. 创建基本结构:它可以帮助用户快速创建项目的基本目录结构,包括主应用程序目录、测试目录、静态文件目录等。 5. 自动生成命令:它可以通过读项目中的代码,生成命令行工具或管理命令,以便用户可以轻松地执行项目相关的任务,如数据库迁移、数据导入等。 6. 提供模板:它提供了一些预定义的模板,可以用作新项目的起点。这些模板包含了一些常用的功能,如用户认证系统、RESTful API等,以减少开发者的工作量。 总结来说,Python3-kickstart是一个强大的工具,可以帮助Python开发者快速启动项目并提高开发效率。无论是创建项目的基本结构,安装依赖库,生成配置文件,还是自动生成命令,它都能帮助开发者省去重复工作,集中精力于开发核心功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值