Algorithm之地图着色问题

地图着色问题

1.1题目描述

已知地图,对各省进行着色,要求相邻省所使用的颜色不同,并保证使用的颜色总数最少。设计对图进行着色的算法,分析该算法的时间空间复杂度,并利用该算法实现对地图着色。

1.2问题分析与解决思路

1.2.1问题分析

问题需要解决对地图上的各省着色时相邻省所使用的的颜色不同且使用的颜色总数最少。这是基本的图论的问题,涉及四色原理。将地图区域之间的邻接关系抽象为图上点与点的邻接关系,此时地图着色问题就转换为图问题:已知一个图,要求给图上每个点上色,并保证该点的颜色与它的邻接点的颜色都不相同。而且还需要将程序所需要的功能模拟着色在编程中实现。

1.2.2解决思路

问题有两个要求:一是相邻的省所使用的颜色不同,另一个是所用颜色最少。

为了保证第一个要求,在给每个省上色前排除其相邻的省已经使用的颜色,使用剩下的可用颜色中的第一种颜色进行着色,上色后就将该颜色排除,避免在回溯时再次使用该颜色,且回溯时会初始化部分或全部的省份颜色和颜色数组。此时设置一个颜色数组存放各省可用颜色,在上色前将相邻省已用颜色的颜色值赋值为0,上色时使用第一个不为0 的颜色值,上色后将该颜色值也赋值为0。

为保证第二个要求,每次用不同的省作为第一个着色省份开始着色。首先使用两种颜色,若在着色时失败则增加到三种颜色进行着色,若三种颜色着色也失败则增加到四种颜色,直至用最少的颜色着色成功。着色成功后用下一个省份作为第一个着色省份开始着色,重复上述步骤,直至用所有省份作为第一个着色省份开始着色,并用最少的颜色成功着色,再通过比较各个省份作为第一个着色省份开始着色,着色成功时所需要的最少颜色数,得出着色所需最少颜色数。可以用循环双链表连接邻接表通过双重循环和回溯来实现。在某个省份上色使用颜色值超过最大可用颜色值时回溯到上一个省份的上色中,上一个省份选择其他可用颜色,继续内层循环。当回溯使第一个省份上色使用颜色超过当前最大可用颜色时,将最大可用颜色加1,重新开始内层循环。当着色成功后内层循环结束,用该省作为第一个着色省份所用着色的颜色数,与最少着色颜色数比较并保存较小值,接着外层循环进入到下一步用另一个省份作为第一个着色省份,直至外层循环结束得出最少着色颜色数。

综合以上,解决该问题,我采用四色定理,使用回溯算法进行着色,就是选择各种颜色,直到把此点着色完为止。

此题也可以用贪心法:选择一种颜色,以任意顶点为开始顶点,依次遍历图中未被着色的每个顶点,如果一个顶点可以用颜色1着色,即当它的邻接顶点还未被着色时,用颜色1为该顶点着色。当没有顶点能以这种颜色着色时,选择颜色2和一个未被着色的顶点作为开始顶点,用第二种颜色为其他顶点尽可能多地进行着色,如果还有未着色的顶点,则选取颜色3为尽可能多的顶点着色,直达所以顶点都被着色。这种算法实质就是选择一种颜色,最大化的将图中的各点都用这个颜色着色。

1.3模型建立与算法描述

我们将上述分析过程和解决的思路进一步归纳为以下步骤:

选取一个省份开始着色,把当前省份的颜色压入一个省份排序的栈中去,栈中对应位置的颜色即为对应省份的颜色,
判断是否省份队列全部颜色都处理完成,是则结束并把颜色标记到地图上,否则继续,
判断当前块颜色的值是否小于5,是则进入下一步,否则把栈顶元素弹出,颜色的值选取弹出元素颜色的下一个,返回第2步。
判断地图是否全部着色,是则结束,标出地图颜色,否则判断当前地图块颜色是否和周围颜色重复,是则判断下一个颜色,否则把当前地图块的颜色设为当前颜色,把地图块压入栈中,判断下一个地图块。
算法伪代码描述:

算法 Map_Color(s[0--n])

//s[0--n]表示省

n=34;//34个省

s[0]=1;//选择第一个区域先着色,颜色为1

area=1;//从第二个区域开始着色

color=1;//从颜色1开始着色

while area <n:

   while color <= 4:

      if area >=n:

          break;

      k=0;//从颜色1开始着色

      while k <area and s[k]*d[area][k]!=color ://判断是否重色

          k++;

      if  k <area:

        color ++;

      else:

         S[area]=color;

         area++;

         color=1;

  if  color>4://如果颜色大于4,说明出现错误,回到上一个区域,重新着色

     area=area-1;

     color =s[area]+1; 

​​​​​​​1.4算法实现与复杂度分析

1.4.1算法实现

算法实现使用到的数据结构为图,邻接矩阵

实现的步骤:

1.将所有省颜色都置零

2.判断有未着色的省,否就结束,是就转到下一步

3.判断是否有颜色可以选取,否则将当前省份颜色置零,返回上一个省,转到第二步;是的话转到下一步。

4.判断是否与相邻省的颜色相同,否就对下一个省份进行着色,转到第二步;是的话就选取另一种颜色着色,转到第三步

1.4.2 算法复杂度分析

空间复杂度上,有用于记录地图中不同区域的邻接关系的邻接链表,有用于记录每个区域颜色的栈,设地图中区域的个数为n,则有邻接链表的大小为n2,存储颜色的栈的大小为n,总的空间用量为n2+n,所以空间复杂度为:O(n)=n2+n

在时间复杂度上,平均情况为:O(n)=n2 ,主要与n的规模有关

​​​​​​​1.5程序实现及运行结果分析

在这里插入图片描述
分析:如图所示,可以实现直接点击“结果”按钮出现回溯的结果,也可以选择“演示”,展示填充过程(事实上是通过Robot类的延时实现的)
这样实现的回溯法其实是需要改进的,可以从两个角度对回溯算法进行改进:

  1. 先给对影响省份数最多的省着色,影响省份数相同时,此时先给剩余可着颜色最少的省着色;
  2. 给某个省着色时,不仅要判断是否与相邻的已着色省份颜色相同,还应该判断是否导致有省份无色可着。
    但是我没做出来。
    相关代码源码
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

daisyr07

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值