第一题

小美是美团的一名鲜花快递员,鲜花是一种保质期非常短的商品,所以需要尽快送到客户手中,公司对于骑手的一个要求就是要规划送花的线路,使得骑手送完所有订单走的路程尽可能少。(骑手开始派送时带走了所有需要派送的花,不必每单后返回花店,路程结算是从花店出发,到送完最后一名客户为止,不计算从最后一名客户家回到花店的时间)

       公司对于骑手的绩效评价是取决于两个指标,一是从花店到所有客户地址的距离之和,另一个是骑手实际走的路程。

      设花店始终位于1号位置,客户共有n-1个,其编号为2~n。令dis(i,j)表示i号位置到j号位置的距离,即分别计算美团 CodeM 初赛 Round B送外卖2 美团骑手测试题答案_最短距离

      为了简化问题,我们约束这n个位置构成的是一棵树,即只有n-1条边在其中互相连接,且保证n个点彼此连通。

 

输入描述:

输出第一行包含一个正整数n,即花店和客户的总数。(1<=n<=30000)

接下来有n-1行,每行有三个整数u,v,w,表示在u和v之间存在一条距离为w的道路。(1<=w<=1000)

输出描述:
输出包含两个整数,中间用空格隔开,分别表示花店到所有客户地址的距离之和和骑手实际走的路程。

示例1

输入
5
1 2 3
1 3 1
1 4 2
2 5 1
输出
10 10

代码如下:
n = int(input())
dic = dict()
stack = []
rd = 0
wd = 0
for _ in range(n-1):
    start, end, dist = [int(x) for x in input().split()]
    if start in dic:
        dic[start][end] = dist
    else:
        dic[start] = {end:dist}
    wd += dist*2
max_path = 0
def search(node, path):
    global rd, wd, max_path
    rd += path
    if node not in dic:
        max_path = max(max_path,path)
    else:
        for k, v in dic[node].items():
            search(k, path+v)
search(1, 0)
print(rd, wd-max_path)

或者

思路:

  1. 求 1~n的距离金和,那我们维护一个数组res来保存1到i的距离,如果中间有中介节点,加上1到中介节点的距离即可
  2. 求最短距离,因为所有1~n所有路径都会走两边,除了那条最长的路径
if __name__ == '__main__':
  n = int(input())
  res = [0] * (n+1)
  sumDis = 0
  maxRoad = 0
  count = 0
  for i in range(n - 1):
      u, v, w = list(map(int, input().split()))
      res[v] = res[u] + w  # Dis(1~v) = Dis(1~u) + Dis(u~v)
      sumDis += res[v]  # 加上1~v的距离
      count += w
      maxRoad = max(maxRoad,res[v])
  print(sumDis,count * 2 - maxRoad)

 

第二题

美团对于商家的评价体系是1-5星评价体系,用户在完成订单之后可以对商家打1/2/3/4/5星,而在客户端上,商家的评级却不一定是整数,而是会显示小数点后的一位。很显然这就需要一个计算器了,小美拥有了一些商户的评价数据,希望可以计算出商家在客户端上显示出的评分。

这个评分的计算非常简单,就是对该商家的所有客户的星级评价做求一个平均,然后去尾法显示小数点后的一位即可,例如平均得分是3.55,则显示的是3.5。例如某商家获得了1-5星评价各一个,则显示的评分是(1+2+3+4+5)/5=3.0。

输入描述:
输入包含5个整数,依次分别表示商家获得1星到5星的评价数量,每一种评价的数量都不大于1000。


输出描述:
输出仅包含一个保留一位的小数,表示商家在客户端上显示的评级。

示例1

输入
2 2 1 1 2
输出
2.8

代码如下:
level = [1,2,3,4,5]  #评分等级
input_1 = list(map(int, input().split(" ")))    #输入
score = [level[i]*input_1[i] for i in range(5)]    #评分等级与数量相乘
if sum(score) == 0:    #若无评分,输出为0.0
    print(0.0)
else:
    print(int(sum(score)/sum(input_1)*10)/10)

 

第三题

2020年的618不再仅仅是购物节啦,同时也是美团外卖节,小美早早就准备好了各种满减代金券,为了最大程度的“省钱”,当然是选择把这些代金券都用光啦!

       这些代金券都有一个使用门槛,即满多少元的订单才可以使用。如果使用一个二元组<x,y>表示一张代金券,即需要满x元才能优惠y元,那么需要注意的是,并不是所有代金券的x都是大于等于y的,良心美团也会推出一些x<y的代金券。如果x<y,例如x=1,y=2,则购买1元商品的情况下无需付款,不会退款给用户。

请问小美如果想用完这些代金券,在保证总付款金额最小的情况下,她最多购买多少钱的外卖呢?

说明:

1.一个订单只能用一张代金券。

2.同时满足总付款金额最少,且购买的外卖价值最高,例如两个优惠完都是1元的外卖,一个原价3元另一个原价4元,则选四元的。

3.由于美团商户很多,所以对于任何一个价格我们都可以找到至少一种商品购买。

 

输入描述:

输入第一行仅包含一个正整数n,表示小美拥有的代金券数量。(1<=n<=50000)

接下来有n行,每行有两个整数x和y,表示一张代金券需要订单金额满x元可以使用,能够优惠y元。(1<=x<=10000,1<=y<=10000)


输出描述:
输出仅包含两个正整数,中间用空格隔开,分别表示小美购买的外卖价值和她的实际付款金额。

示例1

输入
3
5 3
10 5
1 2
输出
17 7

思路:

题目要求实付金额最小的前提下外卖价值(即原价)最高,所以

对于x>y的代金券,一定会购买价值x元的外卖,实付金额为x-y;

对于x<=y的代金券,可以选择购买价值为x到y的外卖,实付金额都为0,而为了使外卖价值最高,我们可以认为这类代金券的x=y;

按照以上过程优化之后,直接对所有代金券的x求和可得到外卖总价值,对所有x-y求和可得到实付金额

代码如下:
n=int(input()) 
lst=[[int(j) for j in input().split()] for i in range(n)]
value=0 # value代表总价值
money=0 # money代表最终的实付金额
for i in range(n):
    if lst[i][0]<lst[i][1]:
        lst[i][0]=lst[i][1]
    value+=lst[i][0]
    money+=lst[i][0]-lst[i][1]
print(value,money)

 

第四题

外卖节即将过去了,小美还有很代金券没有消费掉,美团面向小美这样的用户推出了一个新的活动,即代金券消消乐活动。系统会把小美的代金券打乱顺序排成一排,小美可以进行任意多次如下操作:

       如果存在相邻的两个代金券金额相等,设其面额为x,小美可以使用这两张代金券换一张面额为x+1的代金券,并将其仍放在原来两张券的位置上,每进行一次这样的操作,小美就可以获得1元可以无限期使用的奖励金。

       小美觉得奖励金可太香了,因此她想获得尽可能多的奖励金,请问她最多可以获得多少奖励金。

 

输入描述:

输入第一行仅包含一个正整数n,表示小美拥有的代金券数量。(1<=n<=500)

输入第二行包含n个正整数,每个整数x表示一张代金券的面额,同时这也是系统排出的代金券顺序。(1<=x<=100)


输出描述:
输出仅包含一个整数,表示小美最多可以获得的奖励金数量。

示例1

输入
5
1 1 1 1 1
输出
3
说明

{1,1,1,1,1}->{1,1,1,2}->{1,2,2}->{1,3}

代码如下:

n=int(input())
an=list(map(int, input().strip().split()))
stack=[]
res=0
for num in an:
    if not stack&nbs***bsp;stack[-1]!=num:
        stack.append(num)
    else:
        while stack and num==stack[-1]:
            stack.pop()
            num+=1
            res+=1
            
        stack.append(num)

print(res)