序言
这次刷拼多多编程的笔试题
题目:
小多想在美化一下自己的庄园。他的庄园毗邻一条小河,他希望在河边种一排树,共 M 棵。小多采购了 N 个品种的树,每个品种的数量是 Ai (树的总数量恰好为 M)。但是他希望任意两棵相邻的树不是同一品种的。小多请你帮忙设计一种满足要求的种树方案
输入解释:
第一行包含一个正整数 N,表示树的品种数量。
第二行包含 N 个正整数,第 i (1 <= i <= N) 个数表示第 i 个品种的树的数量。
输出要求:
输出一行,包含 M 个正整数,分别表示第 i 棵树的品种编号 (品种编号从1到 N)。若存在多种可行方案,则输出字典序最小的方案。若不存在满足条件的方案,则输出"-"。
例子如下:
输入:
3
4 2 1
输出:
1 2 1 2 1 3 1
思路:
首先要知道 当某一类树剩余数量大于总数M的一半是不可能有满足条件的方案的
然后,这是个不断剪枝的问题
########################
#由于python 默认递归深度不超过1000,做dfs会比C吃亏
#受限于python默认的最大递归深度,会出现某些数据爆函数栈的问题,而同样的算法使用C++则不会有问题
#手动修改深度
import sys
sys.setrecursionlimit(10000000)
########################
classes = map(int, input().strip().split()) #树的品种
list_class_num = list(map(int, input().strip().split())) #第 i 个品种的树的数量
M = sum(class_num) #总长度
ans = []
def dfs(list_C_N, M, prev):
"""
list_C_N: 代表list_class_num
M:总长度
prev: 录入答案时的树的种类,先给个初始值是0
"""
####################
##当循环到M总长度为0的时候,这个时候可以停止了
if M == 0:
return True
####################
####################
#某一类树剩余数量大于总数M的一半是不可能有满足条件的方案的
for i in range(len(list_C_N)):
if list_C_N[i]*2 > M+1:
return False
####################
####################
#递进
for i in range(len(list_C_N)):
current = i+1
if list_C_N[i] > 0 and prev != current:
list_C_N[i] -= 1
ans.append(current)
#开始进入循环
if dfs(list_C_N, M-1, current):
return True
ans.pop(-1) # 不满足则回退
list_C_N[i] += 1
return False
####################
print(" ".join(map(str, ans)) if dfs(list_C_N, M, 0) else "-")
题目二:
给定一个长度为偶数的数组arr,将该数组中的数字两两配对并求和,在这些和中选出最大和最小值,请问该如何两两配对,才能让最大值和最小值的差值最小
一共2行输入。
第一行为一个整数n
第二行为n个数,组成目标数组,每个数大于等于2,小于等于100。
输出最小的差值。
例子如下:
输入:
4
2 6 4 3
输出:
1
用直接发会导致时间超时
所以,先把序列按大小拍好,然后来一个首尾相加,,再用按大小排好,再首尾相减
代码如下:
n = map(int, input())
lis = list(map(int, input().split()))
#按从小到大排序
lis.sort()
sum_ = []
for i in range(len(lis)//2):
sum_.append(lis[i]+lis[-i-1])
sum_.sort()
print(abs(sum_[-1]-sum_[0]))
题目三:
你在玩一个回合制角色扮演的游戏。现在你在准备一个策略,以便在最短的回合内击败敌方角色。在战斗开始时,敌人拥有HP格血量。当血量小于等于0时,敌人死去。一个缺乏经验的玩家可能简单地尝试每个回合都攻击。但是你知道辅助技能的重要性。
在你的每个回合开始时你可以选择以下两个动作之一:聚力或者攻击。
聚力会提高你下个回合攻击的伤害。
攻击会对敌人造成一定量的伤害。如果你上个回合使用了聚力,那这次攻击会对敌人造成buffedAttack点伤害。否则,会造成normalAttack点伤害。
给出血量HP和不同攻击的伤害,buffedAttack和normalAttack,返回你能杀死敌人的最小回合数
例子:
输入:
13
3
5
输出:
5
思路是:
当buffed attack 大于 两倍的 normal attack,这时 前面都用buffed比较快 只要比较剩余的量是否小于normal,要是小于,则最后一次使用normal attack
当buffed attack 小于 两倍的 normal attack,则这时候 直接都用normal attack
代码如下:
HP = int(input())
normal = int(input())
buffed = int(input())
count = 0
if buffed <= 2*normal:
count = HP//normal
left = HP%normal
if left==0:
count += 0
else:
count += 1
if buffed > 2* normal:
count = (HP//buffed)*2
left = HP%buffed
if left == 0:
count += 0
elif left <= normal:
count += 1
elif left > normal:
count += 2
print(count)