地图染色(四色定理)问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_44116998/article/details/101516781

四色定理
数学语言描述:将平面任意地细分为不相重叠的区域,每一个区域总可以用1234这四个数字之一来标记而不会使相邻的两个区域得到相同的数字。该定义摘自百度百科
问题描述
该定义摘自百度百科
地图着色(map coloring)是一种组合构形,它是对于地图面集的一种分划,分配地图的每一个面一种颜色,使得相邻的面(指有公共边界边)具有不同的颜色,称这样一种色的分配为这个地图的一个着色,或者说,将地图的面集分划为若干个子集,使得每个子集中的任何两面均不相邻,这样就可以将每个子集中的面用一种颜色着染使得不同子集用的颜色不同,在地图M的所有着色中,使用颜色最少的着色的颜色数目称为地图M的色数,地图的顶点着色,或者说,对于与它同构的图的顶点做正常着色,就是其对偶地图的地图着色。
而我们这里要讲的是需要满足的唯一要求就是相邻的部分颜色必须不一样,暂不讨论着色数最少的问题,先实现可实现方案。


思路解答:这个题目很明显需要不断地试错,即将可能的方案都尝试一下,也就是试错的方法,那么采用回溯法或者试探法即可解决该问题。


代码实现:

  1. 明确每个板块颜色的存储表示,可采用一维数组表示,int colorpart[ n ]那么下标colorpart[ i ]中的i可表示板块号,赋值表示涂抹什么颜色,例如1,2,3,4表示四种颜色,colorpart [ 1 ] = 1表示一号板块着色为一号色,依此类推即可。
  2. 每个板块是否相邻,可以用二维数组或者邻接链表表示,如果用二维数组:map[ i ][ j ] = 1可表示 板块 i 和板块 j 相邻,map[ i ][ j ] = 0表示不相邻。邻接链表的话,更节省空间,将每一个板块号作为头节点,后序结点为与之相邻的板块号的结点,表示即可。
  3. 如何判断是否相邻并且颜色是否相同呢?利用 map[ i ] [ k ] * colorpart [ k ]是否等于 目前颜色作为判断条件,满足时,k++,与已经上色的板块比较即可,k作为指向已经着色的板块的临时变量序号,用作遍历判断使用。

代码实现:

#include<iostream>
using namespace std;
void MapColor(int map[][7],int colorpart[])
{
	colorpart[ 0 ] = 1;//0号着色  
	int i = 1 ,j = 1, k;//  i 为区域号,j 为染色号
	while(i < 7)
	{
		while( j < 5 && i < 7 ) 
		{
			k = 0;
			while((k < i) && map[i][k] * colorpart[k] != j )
				 k++;
			if(k < i)//上述判断条件由于颜色相同而跳出循环,更换颜色,继续比较 
				 j++; 
			else
			{
				 colorpart[i++] = j;
				 j = 1;//每次从第一种颜色开始试错 
			}  
		}
		if(j > 4)
			j = colorpart[--i] + 1;  
	}
}
int main()
{
	int map[7][7] ={0 , 1 , 1 , 1 , 1 , 1 , 0,
		     1 , 0 , 0 , 0 , 0 , 1 , 0,
		     1 , 0 , 0 , 1 , 1 , 0 , 0,
		     1 , 0 , 1 , 0 , 1 , 1 , 0,
		     1 , 0 , 1 , 1 , 0 , 1 , 0,
		     1 , 1 , 0 , 1 , 1 , 0 , 0,
		     0 , 0 , 0 , 0 , 0 , 0 , 0};//邻接关系图 
	int colorpart[7];
	MapColor(map,colorpart);
	for(int i = 0;i <= 6;i++)
		cout<<colorpart[i]<<" "; 
	return 0;      
}

输出结果:在这里插入图片描述


四色定理的局限性
在真实的地图着色过程中可能会有一个国家的领土不是相连的,但仍需要着同一种色,这种就增加难度。

猜你喜欢

转载自blog.csdn.net/qq_44116998/article/details/101516781