zoukankan      html  css  js  c++  java
  • 四色标记算法

    著名的四色定理说到,“如果在平面上划出一些邻接的有限区域,那么可以用四种颜色来给这些区域染色,使得每两个邻接区域染的颜色都不一样”

    另一个通俗的说法是,“任意一个无飞地的地图都可以用四种颜色染色,使得没有两个相邻国家染的颜色相同。”

    定理的证明比较复杂,但可以确信:四种颜色是足够染完平面图,并且保证每两个邻接区域染的颜色都不一样。

    在我的研究工作中,需要实现一个这样的算法,最初我用DFS实现,确信思路正确,也测试了几组数据,然而在区域数较多的时候,由于堆栈深度过深,导致程序崩溃(我猜想是这个原因),所以后来尝试用了非递归实现的方法。

    图像处理中的四色标记问题可以定义为:

    给定邻接矩阵 Adj[n][n],其中若第i个区域与第j个区域相邻,则A[i][j]=1,否则A[i][j]=0,求四色标记该区域的一组解(注意:解空间可能达到4^n,故只求一组解)

    /* *************************************
     *           Main Function
     *  Para:
     *      @Adj: Adjacent Matrix
     *      @Record: Record the labeled results
     *      @num: The number of regions
     *
     * *************************************/
    void FourColorLabel(int ** Adj, int * Record, int num)
    {
        // 染色第一个区域,先设置为1
        Record[0]=1;
        int m=1, n=1; // m计数,n为颜色值
        // 一直染色,直到染完
        while (m<=num)
        {
            while(n<=4&& m<=num)
            {
                int k=0;
                for (k=0; k<m; k++)
                {
                    if (Adj[m][k]==1 && Record[k]==n) break; // 染色有冲突
                }
                if (k<m) n++;  // 染色有冲突,换新颜色
                else // 当前染色OK
                {
                    Record[m]=n;
                    m++;
                    n=1;
                }
            }
             if (n>4) // 如果当前用的已经超出标记范围(说明在已标记的情况下,目前区域无合适的颜色,必须回退)
            {
                m--;
                n=Record[m]+1;
            }
        }
    }

     以上的复杂度其实不是很好估计,跟具体的图有关,回退次数不多的情况下,很快就能完成所有染色,否则,需要更多的回退次数。 

     附上我之前用DFS染色的程序示例:

      1 #include <iostream>
      2 
      3 using namespace std;
      4 
      5 /* *************************************
      6  *
      7  *            Four Color Label
      8  *
      9  * *************************************/
     10 
     11 /* *************************************
     12  *           Main Function
     13  *  Para:
     14  *      @Adj: Adjacent Matrix
     15  *      @Record: Record the labeled results
     16  *      @cur: current index
     17  *      @n: The number of regions
     18  *
     19  * *************************************/
     20 void FourColorLabel(int Adj[][7], int* Record, int cur, int n);
     21 
     22 /* *************************************
     23  *           CheckOk
     24  *  Para:
     25  *      @Adj: Adjacent Matrix
     26  *      @Record: Record the labeled results
     27  *      @cur: current index
     28  *      @clabel: The label of cur
     29  *
     30  * Check "color the cur region with clabel" is ok or not
     31  * *************************************/
     32 bool CheckOk(int Adj[][7], int *Record, int cur, int clabel);
     33 
     34 int main()
     35 {
     36 
     37 
     38     /* ****************************************************
     39      *
     40      *     Test CASE
     41      *
     42      *     ----------------------
     43      *     | 1   /   2  /       |
     44      *     |    /-------/   3   |
     45      *     |---/        -------|
     46      *     |     4       /      |
     47      *     |------------/  5    |
     48      *     |             ------|
     49      *     |    6        /      |
     50      *     |            /    7  |
     51      *     ----------------------
     52      * ****************************************************/
     53     int Adj[7][7] = { {0, 1, 0, 1, 0, 0, 0},
     54                       {1, 0, 1, 1, 0, 0, 0},
     55                       {0, 1, 0, 1, 1, 0, 0},
     56                       {1, 1, 1, 0, 1, 1, 0},
     57                       {0, 0, 1, 1, 0, 1, 1},
     58                       {0, 0, 0, 1, 1, 0, 1},
     59                       {0, 0, 0, 0, 1, 1, 0} };
     60 
     61 
     62     int Record[7] = {0};
     63 
     64     FourColorLabel(Adj, Record, 0, 7);
     65 
     66     for(int i=0; i < 7; i++)
     67     {
     68         cout << Record[i] << " ";
     69     }
     70     cout << endl;
     71 
     72     return 0;
     73 }
     74 void FourColorLabel(int Adj[][7], int* Record, int cur, int n)
     75 {
     76     // Index exceed, then return
     77     if(cur<0 || cur >= n)
     78     {
     79         // Break Out
     80         return;
     81     }
     82     int clabel=0;
     83     if(Record[cur] != 0)
     84     {
     85         int flag = 0;
     86         for(clabel = Record[cur]+1; clabel <= 4; clabel++)
     87         {
     88             if(CheckOk(Adj, Record, cur, clabel))
     89             {
     90                 Record[cur] = clabel;
     91                 flag = 1;
     92                 break;
     93             }
     94         }
     95         // IF 成功标记
     96         if(flag == 1)
     97         {
     98             FourColorLabel(Adj, Record, cur+1, n);
     99         }
    100         // ELSE 不成功,返回上一步
    101         else
    102         {
    103             FourColorLabel(Adj, Record, cur-1, n);
    104         }
    105     }
    106 
    107 
    108     int flag = 0;
    109     for(clabel = 1; clabel <= 4; clabel++)
    110     {
    111         if(CheckOk(Adj, Record, cur, clabel))
    112         {
    113             Record[cur] = clabel;
    114             flag = 1;
    115             break;
    116         }
    117     }
    118     // IF 成功标记
    119     if(flag == 1)
    120     {
    121         FourColorLabel(Adj, Record, cur+1, n);
    122     }
    123     // ELSE 不成功,返回上一步
    124     else
    125     {
    126         FourColorLabel(Adj, Record, cur-1, n);
    127     }
    128 
    129 }
    130 
    131 bool CheckOk(int Adj[][7], int* Record, int cur, int clabel)
    132 {
    133     int i = 0;
    134     for(;i < cur; i++)
    135     {
    136         // IF 相邻 && 标记相同
    137         if(Adj[i][cur]==1 && Record[i]==clabel)
    138         {
    139             return false;
    140         }
    141     }
    142     return true;
    143 }
  • 相关阅读:
    进程和线程的概念、区别和联系
    Python高级语法-GIL-理解(4.1.1)
    Web服务器-并发服务器-Epoll(3.4.5)
    Web服务器-并发服务器-长连接(3.4.4)
    Web服务器-并发服务器-单进程单线程非堵塞方式(3.4.3)
    Web服务器-并发服务器-协程 (3.4.2)
    Web服务器-并发服务器-多进程(3.4.1)
    Web服务器-服务器开发-返回浏览器需要的页面 (3.3.2)
    Web服务器-服务器开发-返回固定页面的HTTP服务器(3.3.1)
    Web服务器-HTTP相关-快速整一个服务器响应浏览器(3.2.1)
  • 原文地址:https://www.cnblogs.com/moondark/p/3594188.html
Copyright © 2011-2022 走看看