【笔试题】刺客信条/Assassin’s Creed (阿里巴巴2020.08.26笔试第二题)

题目:

有一个刺客接了一个杀死怪物的任务,他有一把剑,耐久度为m,怪物一共有n个,它们分为两种,一种是不带剑的空手怪物,一种是带剑的怪物,不同的怪物有不同的血量,血量和刺客佩剑的耐久度对应,即杀死a点血的怪物需要消耗a点耐久度。如果杀死带剑的怪物,则可以拿走怪物的剑,怪物的剑比较特殊,它可以无视血量杀死任何一只怪物并且不损失刺客自己剑的耐久度,但是每杀死一个怪物它就会少一点耐久度,耐久度为0则报废。
该刺客对自己的要求很高,要求自己在能杀死更多的怪物的前提下,保证自己佩剑消耗的耐久度最低。


输入
 - n为总共的怪物数,m为刺客佩剑的耐久度;
 - 每个怪物信息包含两个数(a, b), a是怪物的血量,b为怪物的剑的耐久度,a和b分别存在一个列表A和B中。

输出
 - 输出有两个数N、M,N为最终杀死的怪物数,M为刺客佩剑损耗的耐久度。

举例
输入:
n = 3, m = 5
A = [5, 4, 7], B= [1, 1, 7]
输出:
N = 3, M = 4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# 样例1 后面提供了更多的测试样例可供测试
n, m = 3, 5
A = [5, 4, 7]
B = [1, 1, 7]

###############程序开始##################

# 存储所有怪物信息并且按照血量从小到大排序
monsters = sorted([(i, j) for i, j in zip(A, B)], key=lambda x: x[0])

# 记录最后杀死的怪物数以及损耗的耐久度
killed = 0
cost = 0

# monsters_without_sword存储所有Bi为0的空手怪物,monsters_with_sword存储所有Bi不为0的带剑怪物
monsters_with_sword = []

# 先不考虑自动杀死的情况
# 临时存储m
m_tmp = m
kill_only_by_self = 0
for monster in monsters:
# 如果剑的耐久还够杀下一个怪,则继续杀怪
if m_tmp >= monster[0]:
m_tmp -= monster[0]
kill_only_by_self += 1

# 同时将带剑怪物信息存储在monsters_with_sword中
if monster[1] != 0:
monsters_with_sword.append(monster)
# 得到只用自己的剑最多能杀死多少怪物以及所需要的耐久度
cost_only_by_self = m - m_tmp

# 如果所有的怪物都是空手的,则可以直接输出结果
if monsters_with_sword:
# 得到最“脆皮”的带剑怪物
min_monsters_with_sword = min(monsters_with_sword, key=lambda x: x[0])

# 判断起始耐久度是否足够杀死最“脆皮”的带剑怪物
if min_monsters_with_sword[0] <= m:
# 临时存储m
m_tmp = m
# 用自己的剑杀死那个最脆皮的带剑怪物
m_tmp -= min_monsters_with_sword[0]
# 将该怪物从C中删除
monsters.remove(min_monsters_with_sword)

# 存储从怪物身上掉落的所有剑
swords_from_monsters = sum(B)
# 算出除了之前杀死的怪物和能自动杀死的怪物之外还需要用自己的剑杀死的怪物树目
n_t = n - swords_from_monsters - 1

# 记录用自己的剑杀死的怪物数
kill_by_self = 0
for monster in monsters[:n_t]:
m_tmp -= monster[0]
if m_tmp < 0:
killed = swords_from_monsters + kill_by_self + 1
cost = m - m_tmp - monster[0]
break
kill_by_self += 1
else:
killed = n
cost = m - m_tmp

# 比较只用自己剑杀的怪物数和加上自动杀的怪物数
if killed < kill_only_by_self:
killed = kill_only_by_self
cost = cost_only_by_self
elif killed == kill_only_by_self:
# 如果杀的怪物数相同,则取损耗耐久度少的
if cost > cost_only_by_self:
killed = kill_only_by_self
cost = cost_only_by_self
else:
killed = kill_only_by_self
cost = cost_only_by_self
else:
killed = kill_only_by_self
cost = cost_only_by_self

# 输出,killed即为N,cost即为M
print('monsters killed: {}, durability cost: {}'.format(killed, cost))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 样例2
n, m = 2, 1
A = [2, 4]
B = [2, 0]
# output: 0, 0

# 样例3
n, m = 5, 10
A = [4, 2, 4, 5, 10]
B = [0, 0, 1, 1, 1]
# output: 5, 6

# 样例4
n, m = 5, 7
A = [4, 2, 8, 8, 10]
B = [0, 0, 1, 1, 1]
# output: 2, 6

# 样例5
n, m = 6, 10
A = [1, 2, 4, 3, 8, 9]
B = [0, 0, 0, 0, 1, 1]
# output: 4, 9

# 样例6
n, m = 6, 10
A = [3, 4, 5, 1, 1, 1]
B = [0, 0, 0, 0, 0, 0]
# output: 5, 10