华为2019年3月27日实习生笔试题

本文解析了华为2019年实习生笔试中的两道题目:一是求解蜜蜂采集花蜜的最短路径问题;二是计算切水果游戏中完全清除所有水果所需的最少切割次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

华为2019年3月27日实习生笔试题


转自watermelon_learn
第一题还算比较简单,这里就不再叙述了
第二题:简而言之就是TSP问题。蜂巢在坐标(0,0)的位置,有五处花丛,蜜蜂从蜂巢出发,要把五处花丛的花蜜采完再回到蜂巢,最短距离是多少。输入说明:一行输入,10个数分别是五处花丛的坐标(x1,y1,x2,y2,x3,y3,x4,y4,x5,y5),用空格隔开。输出说明:输出最短距离,距离向下取整。时间:C/C++5秒其他10秒

解答:一开始就想到了全排列之后贪心算法取最小,虽然觉得方法太low了,但是让我一下子写出蚁群之类的觉得记忆模糊就很纠结。后来发现这道题给了10秒的运行时间,妥妥的决定用全排列了。思路:先用全排列的方式获取蜜蜂访问5个花丛的所有可能顺序,之后计算每个路径长度取最小

# -*- coding:utf8 -*-
from math import sqrt
line = input().strip().split()
n = list(map(int, line))
n = [int(i) for i in line]
nums = [[0,0], [n[0],n[1]], [n[2],n[3]], [n[4],n[5]], [n[6],n[7]], [n[8],n[9]]]
# 以下为插入的方式获取全排列的代码。没看过别人的,自己想到的。
# 后来看网上说,递归获取全排列更常见,有兴趣的可以自己去搜一下。
order = [[1]]
for i in range(2,6):
    lens = len(order)
    j = 0
    while j < lens:
        for k in range(i-1):
            tmp = order[j][:]  #
            order.append(tmp)
            order[-1].insert(k, i)
        order[j].append(i)
        j += 1
# 接下来是制作距离矩阵
dist = [[0] * 6 for i in range(6)]
for i in range(6):
    for j in range(6):
        if dist[i][j] == 0:
            dist[i][j] = sqrt((nums[i][0]-nums[j][0])**2 + (nums[i][1]-nums[j][1])**2)
        else:
            dist[i][j] = dist[j][i]
# 贪心算法取最小
minVal = 0
for path in order:
    sums = dist[0][path[0]]
    for i in range(4):
        sums += dist[path[i]][path[i+1]]
    sums += dist[path[4]][0]
    if minVal > sums or minVal == 0:
        minVal = sums
print(int(minVal))

第三题:切水果游戏。有一个40×50的方格,里面有n(1≤n≤36)个水果,每一刀可以横切,竖切以及左斜切与右斜切四种方式。想要切完所有水果,最少需要多少刀。输入说明:第一行是说过个数n,接下来的n行是水果的横纵坐标。输出说明:输出最少需要的刀数。(PS:原题有图,这里无图解释一下切割方式,横切就是所有x相同的水果可以一刀切完,纵切就是y相同,左斜切就是x-y相同,右斜切就是x+y相同)。时间:C/C++3秒其他6秒

# -*- coding:utf8 -*-
# 40 * 50的方格
from random import randint
# 动态规划算法。对于一个点,四种切法去除被切除的点即可获得下一次的点集。加上1即可
def dp(points):
    if len(points) <= 1:
        return len(points)
    first = points[0]
    row = [i for i in points if i[0] != first[0]]
    cntRow = dp(row)
    col = [i for i in points if i[1] != first[1]]
    cntCol = dp(col)
    left = [i for i in points if i[2] != first[2]]
    cntLeft = dp(left)
    right = [i for i in points if i[3] != first[3]]
    cntRight = dp(right)
    return 1 + min(cntRow, cntCol, cntLeft, cntRight)
 
 
# 贪心算法。假设只能选择一种方式切,选择刀数最少的
def greedyOne(points):
    x = [i[0] for i in points]
    y = [i[1] for i in points]
    l = [i[2] for i in points]
    r = [i[3] for i in points]
    return min(len(set(x)), len(set(y)), len(set(l)), len(set(r)))
 
 
n = int(input())
points = []
for i in range(n):
    line = input().strip().split()
    x = int(line[0])
    y = int(line[1])
    l = y - x
    r = x + y
    points.append([x, y, l, r])
'''
# 此部分为随机获取点值,确定自己的动态规划算法是否最优
n = 15
for i in range(10):
    points = []
    for j in range(n):
        x = randint(0,40)
        y = randint(0,50)
        l = y - x
        r = x + y
        points.append([x, y, l, r])
    res1 = dp(points)
    res2 = greedyOne(points)
    print('dp is %d, greedy is %d'%(res1, res2))
    if res1 > res2:
        print(points)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值