2017阿里秋招内推在线编程题解法

题目

看了好久才看懂题目,下面是原题的回忆:
有一个取货机器可以在各个巷道间来回移动,同一个巷道里取货不用移动,只需要伸机械臂(所以移动是一维的)。告诉你机器此时在哪条巷道(初始位置),告诉你这个机器要取哪些货物(K种货物),每种货物取多少个(长度为K的数组),再告诉你每个巷道里各种货物的数量(KxN的矩阵,N条巷道)。最后问取完这些货物需要移动的最短距离
这里写图片描述

思路

设想远处的巷道有许多货物,那么只要走到那里吃一口就能把清单清掉。但是走的过程中吃路途中的货物是不费时间的,所以说还不如先把近的货物吃掉。递归地从初始位置开始,由近到远地搜索,返回所有成功取完货物的移动步数,最后取最小值,这也许是个不错的方法,关键点是记录步数和已搜索过的范围,再范围之外搜索。
这里写图片描述

代码

initpos = 2
M = [0,0,0,0,0,0,1]
inventory = [
    [0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1],
]

# 取pos巷道的货物
def drop(pos, M):
    for i in range(len(M)):
        M[i] -= inventory[i][pos]

# 还原M
def plus(pos, M):
    for i in range(len(M)):
        M[i] += inventory[i][pos]

# 找最短移动距离,left, right指示已经搜索过的范围,
# step记录移动步数,pos为当前搜索位置
def find(pos, M, step, left, right):
    # 搜索位置超出范围结束递归
    if pos < 0 or pos >= len(inventory[0]):
        return -1

    drop(pos, M)
    if max(M) <= 0: # 若清单的货物都取够了个,返回步数
        plus(pos, M)
        return step 

    # 初始状态,向左一格或向右一格搜索
    if pos == left and pos == right:
        result1 = find(left-1, M, step+1, left-1, right)
        result2 = find(right+1, M, step+1, left, right+1)
    # 若当前位置在查找过的范围左边缘,向左跳一格,
    # 或跳到右边缘右边一格(移动right+1-pos步)
    elif pos == left:
        result1 = find(left-1, M, step+1, left-1, right)
        result2 = find(right+1, M, step+(right+1-pos), left, right+1)
    # 若当前位置在查找过的范围右边缘,
    # 向右跳一格或跳到左边缘左边一格(移动pos-(left-1)步)
    elif pos == right:
        result1 = find(right+1, M, step+1, left, right+1)
        result2 = find(left-1, M, step+(pos-(left-1)), left-1, right)
    else:
        raise Exception

    plus(pos, M) # 退出递归前要把M还原,避免干扰别的递归步骤

    # 我这里超出范围的情况result为负数,所以只比较正数的最小值
    if result1 >= 0 and result2 >= 0:
        return min(result1, result2)
    elif result1 >= 0:
        return result1
    elif result2 >= 0:
        return result2
    else:
        return -1

print(find(initpos, M, 0, initpos, initpos))

本解法仅供参考,这是我后来想的解法,当时答的时候写了很多错误

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值