有趣的题目:四色着色问题算法研究

来源:互联网 发布:石油进口数据 编辑:程序博客网 时间:2024/06/06 20:52

一、引言

最近,有位朋友有道有意思的题找我看看,正好最近也闲,也就看了看,做了四个多小时,觉得非常有趣。

这是一道什么题目呢?

输入一系列字符阵列,将这些字符阵列每一种看做是一个区域,将每个区域进行着色(也就是替换成四种符号显示),要求每个区域相邻之间不能有相同的颜色。

题意其实不用深究,看到这里也就大概懂了,我们手上得到了一个二维数组,都是字符的,然后一种字符代表一个区域,然后我们要用四种颜色区分这些区域,要求不能相邻区域使用同样的颜色。

数学上有一个非常著名的猜想,叫做“四色猜想”:

四色定理(世界近代三大数学难题之一),又称四色猜想、四色问题,是世界三大数学猜想之一。四色定理的本质许多人认为是在平面或者球面无法构造五个或者五个以上两两相连的区域。

这也是这道题为什么指定只需要 4 种颜色的原因,因为 4 种颜色足足够了。

二、算法如何实现?

思考了很久,最后的实现策略如下:

  1. 首先需要遍历这个二维数组,获得 “字符” 到 “相邻字符数组”的映射关系

  2. 记录当前字符的相邻字符们用掉的颜色(因为相邻不能相同,所以相邻字符用掉的颜色不可以再使用),取第一个可以使用的颜色作为当前字符的颜色值

  3. 检查当前字符的相邻字符是有有未着色的字符点,如有的话,则将此相邻字符看作当前字符,进入步骤 2 ;
    如果遍历完了整个相邻字符都没能找到未着色的字符点的话,那就返回当前函数自动进入上一个当前点的遍历过程,继续步骤 3

  4. 依次类推,直到第 3 步回退到第一个点返回,我们就得到了记录了 “字符”和 “颜色” 的关系记录了

思路比较清晰的话,代码实现也就很简单了:

   /*    * 函数作用  :迭代计算各种字符的颜色    * 参数        :当前处理字符 ; 由 “字符” 到 “相邻字符数组” 的映射    * 返回值       :处理 private 变量 item_color,其记录每种字符的颜色值    */    void tryToSetColor(char cur, unordered_map<char, vector<char>> items_border)    {        // 记录已经用掉的颜色:即当前点的相邻点用掉的颜色        // 将用掉的颜色结果存储到 “无序set” 中去        unordered_set<char> used_color;        for (auto border_use_color : items_border[cur]) {            if (item_color[border_use_color] != '\0') {                used_color.insert(item_color[border_use_color]);            }        }        // 每种字符在四种颜色遍历的情况下取色处理        for (auto color : colors) {            // --找到可以使用的颜色            if (used_color.find(color) == used_color.end()) {                // ----着色成功                item_color[cur] = color;                // ----查看当前点的相邻点是否有未着色的点,若有则进行着色处理                for (auto border_item : items_border[cur]) {                    if (item_color[border_item] == '\0') {                        // ------迭代进行着色处理                        tryToSetColor(border_item, items_border);                    }                }                // 全部着色完毕,返回                return;            }         }    }

这里只贴出了最重要的控制第 2 步和第 3 步迭代循环的函数,若想要了解更全面的代码,请点击这里查看我的 GitHub 地址FourColorMatrix。

三、总结

算法题做的过程是痛苦的,也许就是为了 debug 那么几行代码的错误,也要跟着走好多好多遍 case。

这个程序我是一步一步 debug 出来的,哈哈,也是逻辑思维能力不行的体现。

不过这又怎样呢?

我不照样喜欢算法吗,哈哈哈~~~

0 0