用贪婪算法解决邮差问题

作者: 不如葱油饼 | 来源:发表于2018-02-23 11:33 被阅读222次

现在想起大二的时候的离散数学仍是心有余悸。现已时隔多年,依稀记得邮差问题还有一个贪婪算法。主要是简单易懂吧。但是一说起来,难度刚好的把才学的matplotlib库拿来练习。国安民乐,岂不美哉?
首先准备一下贪婪算法的基本思想:

在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。

贪婪算法不是对所有问题都能得到整体最优解,关键是贪婪策略的选择,选择的贪婪策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。

接着自己给自己设计题目:

要求26个地点,要求最短路径走完所有的点,并绘制路线图。太难了不敢做,先从简单做起吧。

one出题

那么首先我们首先随机生成26个点吧,不然手写得到啥时候去。还要出题的时候偷懒了。26个点,就26个字母表示吧

import random
name = 'abcdefghijklmnopqrstuvwxyz'
points = {}
for i in name:
    x = random.randint(0, 100)
    y = random.randint(0, 100)
    points[i] = (x, y)

这里随机生成0-100的xy坐标,记录到points中去,这个字典我们打印出来就是这个样子。
{'a': (90, 65), 'b': (15, 12)...

two距离计算函数

现在,有一个动作会重复计算,那就是计算两点距离,那就写一个函数,这样每次用就方便了

def len_point(x, y):
    a = (y[0] - x[0]) ** 2
    b = (y[1] - x[1]) ** 2
    c = a + b
    length = round(c ** 0.5, 2)
    return length

这应该是初中内容,那就没啥说的了。只是要注意这是针对我们的坐标格式写的,要针对不同情况不同写。

three开始计算距离

首先我们要走几次肯定是知道的

times = len(points) - 1  

复制一个列表方便我们瞎折腾,可不能把这个表搞乱了。
建一个列表存路径,一个列表存每次走的距离。
然后第一步还是要我们确定的,那就定A点吧。

points_c = points.copy()
min_p_group = ["a"]  # 给出一个列表存路径
min_d_group = []  # 储存每次走的距离
first_p = points_c["a"]  # 给出第一个点
del points_c['a']  # 删除第一个点

那么方法就是循环26次,每一次计算该点与剩下点的距离,找到最小值。把该点记录到路径中,再从原列表删除该点。

for i in range(0, times):
    key_points = []
    for key in points_c.keys():
        key_points.append(key)  # 计算还要走几个点

    min_p = len_point(first_p, points[key_points[0]])  # 第一步
    p_number = 0  # 重置点位置
    for i in range(0, len(points_c)):
        length = len_point(first_p, points[key_points[I]])
        if length < min_p:
            min_p = length  # 储存最短路径
            p_number = i  # 储存最短路径的位置
    min_p_group.append(key_points[p_number])  # 将最短路径的位置保存
    min_d_group.append(min_p)
    first_p = points_c[key_points[p_number]]  # 将最短路径位置保存下一个开始
    del points_c[key_points[p_number]]  # 从字典里删除这个点

好了,现在最短路径已经存在min_p_group中了,顺便我也记了下每次的距离在min_d_group ,就是这样

['a', 'v', 'd', 'p', 'j', 'x'...
[6.08, 12.53, 9.06, 8.54...

four画图

再复制个列表画图用。
准备搞两张图,一张光画点,一张连起来。
因为知道matplotlib是要用到xy坐标的,所以先见p_x,p_y两个列表准备用。

import matplotlib.pyplot as plt
points_d = points.copy()
p_x = []  # 储存x坐标
p_y = []  # 储存y坐标

第一张图我们就随便画了只要把所有点画上去就好了所以画图的参数用‘o',顺便也把尺寸啊,名字什么的定一下,

for value in points_d.values():
    x = value[0]
    p_x.append(x)
    y = value[1]
    p_y.append(y)
plt.subplots(2,2,figsize=(10,5))#规定两张图的尺寸
plt.subplot(121)  # 第一张图
for key in points_d.keys():
    plt.annotate(key, xy=points_d[key])#给每个点标注
plt.plot(p_x, p_y, 'o')

第二张图呢就稍微复杂一点,每两点之间画一次。

plt.subplot(122)  # 第二张图
plt.title("TPS routes")
for key in points_d.keys():
    plt.annotate(key, xy=points_d[key])
for i in range(0, times):
    plt.plot([points_d[min_p_group[i]][0], points_d[min_p_group[i + 1]][0]],
             [points_d[min_p_group[i]][1], points_d[min_p_group[i + 1]][1]], '-o')

five大功告成

plt.show() 

这样我们就得到了一张路线图,感觉还是可以的哈。


路线路

six总结

这次用到代码的都是很基础的东西,用到的理论也实在是令我一个数学系的产品狗汗颜,自然代码的写法也是相当稚嫩。
这算是我第一篇关于代码的文字,是沿着前面的登山者留下来的帐篷和继续向上延伸的脚印。当我可能到达某个高度时再回首这个标记可能哑然失笑,不过那肯定是会心的。

相关文章

  • 用贪婪算法解决邮差问题

    现在想起大二的时候的离散数学仍是心有余悸。现已时隔多年,依稀记得邮差问题还有一个贪婪算法。主要是简单易懂吧。但是一...

  • 算法的设计思想1

    1.贪婪算法 一、 贪婪算法的优点是简单直观,易于实现。缺点是在解决问题的策略上目光短浅。这种算法每当遇到满足问题...

  • 贪婪算法

    贪婪算法(Greedy Algorithm)也叫算贪心法,贪婪法.它是一个遵循启发式解决问题的算法范式.它的核心思...

  • 《算法图解》note 8 贪婪算法

    这是《算法图解》的第八篇读书笔记,主要内容是贪婪算法的简介。 1.定义 贪婪算法()是指在解决问题的每一个步骤中,...

  • 算法(七):图解动态规划

    算法简介 动态规划,将大问题划分为小问题进行解决,从而一步步获取最优解的处理算法 与贪婪算法区别 2者都是将大问题...

  • 大咖20行Python代码玩转算法!涉及到算法就觉得很难?颠覆认

    算法指解决问题准确而完整的方案描述,是解决问题的清晰指令,用系统的方法去描述解决问题的策略机制。 LRU是算法的一...

  • 抖音算法了解--更好的玩转抖音

    科普 什么是算法 定义原意:算法(Algorithm)代表着用系统的方法描述解决问题的策略机制。 算法有什么用 算...

  • 时间复杂度及其计算

    何谓算法? 算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策...

  • 算法的定义

    1.算法是什么 算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题...

  • 代码小工蚁的#《算法图解》#学习笔记-C8贪婪算法

    代码小工蚁的#《算法图解》#学习笔记-C8贪婪算法C8 贪婪算法greedy algorithms 一、贪婪算法 ...

网友评论

本文标题:用贪婪算法解决邮差问题

本文链接:https://www.haomeiwen.com/subject/rewtxftx.html