网易面试题堆棋子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)中
解题思路:
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个点同理。