算法思路
本题可以简化成寻找N个城市x,y坐标的中位数dx,dy,解决方法就是利用最经典的分治算法的思路,通过不断递归与快速排序实现。本程序使用Python实现。
Readme
运行环境:
win10 + pycharm + python3.7
运行说明:
7个.dat后缀文件保存了7组地址数据,将.py和.exe和.dat文件放在同一个文件夹中。直接运行postoffice.exe,将显示每组数据的邮局坐标,和所有城市到邮局的距离总和。程序窗口将保持60秒。
数据结构:
定义列表x存储城市的x坐标,定义列表y存储城市y坐标
算法设计:
1、首先获取每个城市的x,y坐标数据,分别将其存入x和y的列表中。
2、对x、y列表分别使用分治算法,选定列表中最后一个元素作为主元。将列表中每个元素与主元比较,利用快速排序,分成比主元小的和比主元大的两组,中间数据为主元。接下来不断递归,直到列表排序完成。
3、分别取x、y列表的中位数dx和dy,(dx,dy)即为邮局地址坐标。
代码
import time
def readfile(path): #读取文件函数
x = [] #定义列表x用于存放城市的x坐标
y = [] #定义列表y用于存放城市的y坐标
f=open("./"+path)
N = f.readline() #读入N,为该组数据城市个数
for i in range(int(N)):
line = f.readline()
curLine = line.strip().split(" ")
x.append(curLine[0])
y.append(curLine[-1])
return x,y,N
def quicksort(left,right,a): #快速排序功能函数
if(left<right):
p= divide(left,right,a) #使用分治算法
quicksort(left,p-1,a) #递归使用快排,排序主元左侧数据
quicksort(p+1,right,a) #递归使用快排,排序主元右侧数据
return a
def divide(left,right,a): #分治算法功能函数
x = a[right] #将最后一个元素定义为主元
i = left-1 #i是最后一个小于主元的数的下标
for j in range(left,right):
if(a[j]<x):
i += 1
temp = a[i]
a[i] = a[j]
a[j] = a[i]
a[right] = a[i+1]
a[i+1] = x
return i+1
def MinSum(x,y,N): #计算城市与邮局的距离函数
distance=0 #初始距离总和为0
quicksort(0,N-1,x) #对城市坐标列表x进行快排
quicksort(0,N-1,y) #对城市坐标列表y进行快排
dx=x[int(N/2)] #取邮局x坐标为列表x中位数
dy=y[int(N/2)] #取邮局y坐标为列表y中位数
for i in range(N):
distance += abs(int(x[i])-int(dx))+abs(int(y[i])-int(dy))
print("邮局坐标位置为:(" + dx+"," + dy +")")
print("所有居民到邮局距离总和为:",distance)
def main(): #主函数
for i in range(7): #循环读入七个配置文件数据
path = "input_assign01_0{}".format(str(i + 1)) + ".dat"
x, y, N = readfile(path)
print("第%d组数据" % (i + 1))
MinSum(x, y, int(N)) #计算距离
if __name__ == "__main__":
main()
time.sleep(60) #程序睡眠60s