网易面试题堆棋子python版

题目描述

小易将n个棋子摆放在一张无限大的棋盘上。第i个棋子放在第x[i]行y[i]列。同一个格子允许放置多个棋子。每一次操作小易可以把一个棋子拿起并将其移动到原格子的上、下、左、右的任意一个格子中。小易想知道要让棋盘上出现有一个格子中至少有i(1 ≤ i ≤ n)个棋子所需要的最少操作次数.

输入描述:

输入包括三行,第一行一个整数n(1 ≤ n ≤ 50),表示棋子的个数
第二行为n个棋子的横坐标x[i](1 ≤ x[i] ≤ 10^9)
第三行为n个棋子的纵坐标y[i](1 ≤ y[i] ≤ 10^9)

输出描述:

输出n个整数,第i个表示棋盘上有一个格子至少有i个棋子所需要的操作数,以空格分割。行末无空格

如样例所示:
对于1个棋子: 不需要操作
对于2个棋子: 将前两个棋子放在(1, 1)中
对于3个棋子: 将前三个棋子放在(2, 1)中
对于4个棋子: 将所有棋子都放在(3, 1)中
示例1

输入

复制
4
1 2 4 9
1 1 1 1

输出

复制
0 1 3 10

解题思路:

https://blog.csdn.net/qq_34617032/article/details/78578936

 

开始想的有问题,后来看了这篇文章才想明白。感谢

描述一下思路,

这道题就是考利用曼哈顿距离计算,几个点之间的最短汇集路径。通俗的说就是如何移动最短的路径把棋子聚集到一个点上。

那么首先要确定几个棋子之间可能的汇聚点

1 2 4 9
1 1 1 1
如题所述首先考虑的是,x轴的取值范围应该1-9,y轴的取值范围是1-1. 汇聚点应该在这个矩形中间的。所以我开始的思路取汇聚点的范围比较大。
但是后来做了几个实验,发现 用x轴的 1 2 4 9 和y轴 1 1 1 1,进行交叉组合,最后的汇聚点就在其中。现在还没太想明白。但是结果是正确的。

接下来第二步,
计算每个汇聚点到各个棋子的距离,并将结果进行排序。
如 某点 最后的 到各个棋子的距离是 【1,3,5,4】,排序后【1,3,4,5】
下一步 将【1,3,4,5】 调整为 取i个棋子的最短距离,【1,4,8,13】。就是一个累加的过程,分别表示1个棋子,2个棋子,3个棋子,4个棋子的最短距离。
最后,每一次计算,都将其和最低值进行比较,取各自的最低值,就是最后的解。
M=int(input())
k1=input()
k2=input()
# M=4
# k1='1 2 4 9'
# k2='1 1 1 1'
# k1='5 7 6 6'
# k2='2 2 1 3'
k3=[int(x) for x in k1.split()]
k4=[int(x) for x in k2.split()]

#初始化结果矩阵
result=[9999999999]*M
#曼哈顿距离计算
for x in k3:
    for y in k4:
        man_list=[]
        for z in range(M):
            man_list.append(abs(x-k3[z])+abs(y-k4[z]))
        man_list.sort()

        # 逐个比较每个点 到各个棋子处的距离,并按输出顺序输出
        suma=0
        for i in range(M):
            suma+=man_list[i]

            if suma<result[i]:
                result[i] =suma
# #拼成字符串输出
print(' '.join(map(str, result)))

  最后这道题其实还有一个思路,这是宝贝女儿想的。

# k1='5 7 6 6'
# k2='2 2 1 3'
以这题为例, 先说计算4个点汇到一处的计算方法。 x=(5+7+6+6)/4=6,y=(2+2+1+3)/4=2 那么直接计算一个点(6,2) 到各个点的曼哈顿距离就可以了。这样算法效率会大大提升。
当然如果出现小数的情况,还要具体比较相邻的点。例如 (2.5,3.4) 那么就计算四个点就好(2,3)(2,4)(3,3)(3,4)。速度应该也会很快的。

当然 还要考虑 求 2个棋子的,3个棋子的情况下,程序如何做。思路还是从中心点考虑入手,做减法,求3个棋子的时候,就将离中心点最远的子除去即可。2个点同理。


 

posted on 2020-01-31 23:31  耀扬  阅读(485)  评论(0编辑  收藏  举报

导航