算法设计与分析:实验三 回溯法——地图填色问题

实验内容与要求:

问题描述:

我们可以将地图转换为平面图,每个地区变成一个节点,相邻地区用边连接,我们要为这个图形的顶点着色,并且两个顶点通过边连接时必须具有不同的颜色。附件是给出的地图数据,请针对三个地图数据尝试分别使用5个(le450_5a),15个(le450_15b),25个(le450_25a)颜色为地图着色。

实验要求:

对下面这个小规模数据,利用四色填色测试算法的正确性;

对附件中给定的地图数据填涂;

随机产生不同规模的图,分析算法效率与图规模的关系(四色)

基本回溯算法

思路

  • 从图的第一个节点开始,尝试为其染色。
  • 对于当前节点,尝试为其选择一种颜色,然后递归地尝试为其相邻的未染色节点染色。
  • 如果染色过程中出现了冲突,即当前节点与已染色的相邻节点颜色相同,就回溯到上一步重新尝试其他颜色。
  • 当所有节点都染色完毕,即递归到最后一个节点时,找到了一种合法的染色方案,返回 1。
  • 统计所有合法染色方案的数量,并返回结果。

 思维导图

伪代码

深搜回溯函数

  1. function DFS1(x):
  2.     // 如果已经遍历完所有节点,则返回 1 表示找到了一种合法的染色方案
  3.     if x > n:
  4.         return 1
  5.     cnt = 0
  6.     u = id[x] // 当前节点的编号
  7.     // 遍历尝试每一种颜色
  8.     for i from 1 to MAXCOL:
  9.         valid = true
  10.         // 遍历当前节点之前的节点(即染过的节点)
  11.         for j from 1 to x - 1:
  12.             // 如果当前节点与之前染色的节点相邻且颜色相同,则该颜色不合法
  13.             if link[u][id[j]] and color[id[j]] == i:
  14.                 valid = false
  15.                 break
  16.         // 如果当前颜色合法,则尝试用该颜色染色当前节点并继续递归
  17.         if valid:
  18.             color[u] = i // 尝试用颜色 i 染色节点 u
  19.             cnt += DFS1(x + 1) // 继续递归下一个节点
  20.     return cnt
  21. function Solve1():
  22.     // 初始化 color 数组,全部置为 0,表示未染色
  23.     initialize color array with zeros
  24.     // 调用深度优先搜索函数从第一个节点开始染色
  25.     return DFS1(1)

运行结果

由运行结果可以看出得到正确的填色方案数为480,但是运行时间为0.00ms,应该是因为数据规模较小,导致程序执行速度非常快,低于计时的精度。

算法过程:

在着色尝试过程中,依次尝试可用的颜色,并更新与当前节点相邻的节点的颜色状态,剔除不可用的颜色。若成功找到一种着色方案,即所有顶点都被成功着色,则返回 True。下面图示以其中一种染色方案为例(从左往右,从上往下):

 

时间复杂度

  • 在每一次递归调用 DFS1 中,对当前节点进行颜色的尝试,最多需要尝试 MAXCOL 种颜色,所以对于每一个节点,该部分的时间复杂度为 O(MAXCOL)。
  • 在每一次颜色尝试中,需要遍历当前节点的所有邻接节点,最坏情况下,有 x-1 个邻接节点,因此该部分的时间复杂度为 O(x)。
  • 因为递归调用会在每个节点处进行,总的递归调用次数最多为节点数量 x。
  • 因此,总的时间复杂度为 O(x * MAXCOL * x) = O(x^2 * MAXCOL)。即O(n^3),这是一个巨大的指数级别,如果节点数量较少,并且最大可选颜色数量也不是很大时,算法的性能是可以接受的,但是一旦数量增加就很难运行出结果,所以我们一定要对此回溯法进行优化。

 优化深搜回溯算法

四种深搜回溯优化剪枝优化搜索顺序,排除等效冗余࿰

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值