一、实验目的与要求
实验目的:锻炼数据结构、算法设计与实现能力。
实验要求:
1.熟悉数据结构、离散数学、算法设计等课程。
2.对实验题目进行分析,选取适当的数据结构和算法设计方法。
3.进行程序编写和调试工作。
二、实验内容
在一个按照东西和南北方向划分成规整街区的城市里,n个居民点散乱地分布在不同的街区中。用x坐标表示东西向,用y坐标表示南北向。各居民点的位置可以由坐标(x,y)表示。街区中任意两点(x1,y1)和(x2,y2)之间的距离可以用数值|x1-x2|+|y1-y2|度量。居民们希望在城市中选择建立超市的最佳位置,使n个居民点到超市的距离总和最小。
编程任务:给定n个居民点的位置,编程计算n个居民点到超市的距离总和的最小值。
输入:输入由多组测试数据组成。每组测试数据输入的第1行是居民点数n,接下来n行是居民点的位置,每行两个整数x和y。
输出:对应每组输入,输出数据是n个居民点到超市距离总和的最小值。
输入示例:5 居民点到超市最小距离和:10
1 2
2 2
1 3
3 -2
3 3
三、实验设计
此次实验设计采用python编程环境,共分为三部分设计,如下:
1)UI交互界面设计
共提供两个选项供用户选择:①自行输入居民位置 ②随机生成居民位置
自行输入位置部分,由用户输入相应序号,随后按照所出现的提示依次输入即可。
随机生成位置部分,由用户输入相应序号,随后输入用户数量,此次设计生成位置x,y坐标均在-50到50之间,如有需要在相应位置可自行更改。使用random模块中的randint()函数。
2)算法设计
由用户输入的位置或随机生成的位置横纵坐标分别存入datax,datay两个列表当中。此处本人设计get_median()函数,返回列表中位数。随后分别对两个列表进行所需计算,最终得到超市的位置。
get_median()函数:功能为取中位数,设计思路:首先对传入的列表进行排序,采用位运算中half + ~half = -1作为定位工具,返回的(data1[half]+data1[~half])/2 即为列表中位数。
3)绘图设计
特别引入numpy及matplotlib模块,若需运行下列程序读者可能需要自行安装上述模块(有些软件中不自带上述模块),采用scatter()函数,传入点坐标,随后使用show()函数可绘制得到散点图,本人另对点的颜色进行了标注,所得图中红色点为居民位置,蓝色点为超市位置。
四、核心程序代码
# -*- coding: utf-8 -*-
import random
import numpy as np
import matplotlib.pyplot as plt
# 取中位数
def get_median(data):
data1=data[:]
data1.sort()
half = len(data1)//2
return (data1[half]+data1[~half])/2 #此处算法应用 half + ~half = -1
# 自行输入位置
def myinput():
n = int(input('居民数量:'))
print("请输入各居民位置:")
for i in range(n):
x, y = map(int, input().split())
datax.append(x)
datay.append(y)
# 随机生成位置
def rando():
n = int(input('居民数量:'))
print("生成各居民位置如下:")
for i in range(n):
x = random.randint(-50, 50)
y = random.randint(-50, 50)
datax.append(x)
datay.append(y)
print(x,y)
def menu():
print("----**************欢迎使用超市选址系统**************----")
print(" 1 自行输入居民位置 ")
print(" 2 随机生成居民位置 ")
print("----*********************************************----")
print("您的选择是:")
menu()
datax = []
datay = []
c = input()
if c == '1':
myinput()
elif c=='2':
rando()
else:
print("请输入正确选项!")
median_x = get_median(datax)
median_y = get_median(datay)
length_x = 0
length_y = 0
for xi in datax:
length_x += abs(xi-median_x)
for yi in datay:
length_y += abs(yi-median_y)
print("超市坐标为: %d,%d " %(median_x,median_y))
print ("居民点到超市最小距离和为 %d " %(length_x+length_y))
#以下为绘图界面
plt.title('Supermarket Setting')
plt.xlabel("x",fontsize=12)
plt.ylabel("y",fontsize=12)
#plt.tick_params(axis='both',which='major',labelsize=12)
for j in range(len(datax)):
plt.scatter(datax[j],datay[j],s=10,color='r')
plt.scatter(median_x,median_y,s=20,color='blue')
plt.show()
五、实验结果
1 由用户自行输入居民位置
1)测试一:(实验要求中数据)
测试数据: 5
1 2
2 2
1 3
3 -2
3 3
测试结果:
所得坐标图:(居民位置点为红色,超市位置点为蓝色)
2)测试二:(自备数据)
测试数据: 4
-1 1
-1 -1
1 1
1 -1
测试结果:
所得坐标图:(居民位置点为红色,超市位置点为蓝色)
2 随机生成居民位置
1)测试一:
测试数据: 居民数量:5
居民位置:随机生成
测试结果:
所得坐标图:(居民位置点为红色,超市位置点为蓝色)
2)测试二:
测试数据: 居民数量:10
居民位置:随机生成
测试结果:
所得坐标图:(居民位置点为红色,超市位置点为蓝色)
六、实验总结
设计起初考虑可以使用Matlab编译环境,但为使实验更具挑战性,选用python编译环境,在函数设计部分需要注意python中的浅拷贝与深拷贝问题,前者两变量公用一个位置,会同时更改(在排序时会更改列表内容),后者采用y=x[:]语句,使y成为一个新的变量,不会出现上述问题,而在绘图部分,由于本人的软件(pycharm)中并不包含numpy与matplotlib模块,通过在网上爬取教程完成安装,学习到了此模块中常用的函数,在使用python环境绘制坐标图方面有显著提升,而使用python环境所得坐标图的不足在于无法在坐标图上直接显示其坐标,也算使本人功力尚浅,还需要在此方面进一步学习提升。