中国地图着色问题


中国地图着色问题:在中国地图中对各省进行着色,相邻省所使用的颜色不同,并保证所用颜色最少

 解决中国地图着色问题,有两个方面的要求,一个是相邻省所使用的颜色不同,另一个是所用颜色最少。实现这两个要求的思路如下:

一、为保证相邻省所使用的颜色不同,在给每个省上色前排除其相邻省已用颜色,使用剩下的可用颜色中的第一种颜色进行着色,上色后也将该颜色排除,避免在回溯时再次使用该颜色,且回溯时会初始化部分或全部的省份颜色和颜色数组。    

具体实现方法:设置一个颜色数组存放各省可用颜色,在上色前将相邻省已用颜色的颜色值赋值为0,上色时使用第一个不为0 的颜色值,上色后将该颜色值也赋值为0。

二、为保证所用颜色最少,每次用不同的省作为第一个着色省份开始着色。首先使用两种颜色,若在着色时失败则增加到三种颜色进行着色,若三种颜色着色也失败则增加到四种颜色,直至用最少的颜色着色成功。着色成功后用下一个省份作为第一个着色省份开始着色,重复上述步骤,直至用所有省份作为第一个着色省份开始着色,并用最少的颜色成功着色,再通过比较各个省份作为第一个着色省份开始着色,着色成功时所需要的最少颜色数,得出着色所需最少颜色数。

具体实现方法:用循环双链表连接邻接表通过双重循环和回溯来实现。在某个省份上色使用颜色值超过最大可用颜色值时回溯到上一个省份的上色中,上一个省份选择其他可用颜色,继续内层循环。当回溯使第一个省份上色使用颜色超过当前最大可用颜色时,将最大可用颜色加1,重新开始内层循环。当着色成功后内层循环结束,用该省作为第一个着色省份所用着色的颜色数,与最少着色颜色数比较并保存较小值,接着外层循环进入到下一步用另一个省份作为第一个着色省份,直至外层循环结束得出最少着色颜色数。

源程序如下,可在Dev C++下运行,在VS中可能需稍作修改。

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include "string.h"
#include<time.h>
typedef struct ArcNode{
 int apn;    //相邻省序号           
 struct ArcNode *nextarc;//指向下一个结点
}ArcNode;

typedef struct VNode{ 
    char name[6];  //省份名字
 int color;   //省份颜色
 int number;         //省份序号
 ArcNode *firstarc; //头节点
}VNode; 

typedef struct DNode  //定义双链表结点类型
{
 struct VNode  *data;
 struct DNode *prior; //指向前驱结点
 struct DNode *next;  //指向后继结点
}DLinkNode;

ArcNode *node[145],*p;
VNode province[35];
int color[35][5];                                            //颜色数组
void Intput(VNode*province,ArcNode*node[]);      //输入中国地图信息
void Initialization(VNode*province);       //初始化各省颜色及颜色数组
void Painting(VNode*province,ArcNode*p,int i);     //上色
void Setcolor(int i);                                           //设置输出颜色
void Output(VNode*province,ArcNode*p);       //输出信息
void Find(DLinkNode *&L,VNode*province,ArcNode*p);    //求最少着色颜色数
void CreateListR(DLinkNode *&L,VNode*province,int n);   //尾插法建双链表
int main(){
 DLinkNode *DuLinkLis;
 Intput(province,node);
 CreateListR(DuLinkLis,province,34);
 Find(DuLinkLis,province,p);
 return 0;
}
void Intput(VNode*province,ArcNode*node[]){
 for(int i=1;i<145;i++)
 node[i]=(ArcNode *)malloc(sizeof(ArcNode));
 for(int i=1;i<145;i++)
 node[i]->nextarc=node[i+1];
 
 strcpy(province[1].name,"新疆");
 province[1].firstarc = node[1];
 node[1]->apn = 2;
 node[2]->apn = 3;
 node[3]->apn = 4;
 node[3]->nextarc=NULL;
 
 strcpy(province[2].name,"西藏");
 province[2].firstarc = node[4];
 node[4]->apn = 1;
 node[5]->apn = 3;
 node[6]->apn = 7;
 node[7]->apn = 8;
 node[7]->nextarc=NULL;
 
 strcpy(province[3].name,"青海");
 province[3].firstarc = node[8];
 node[8]->apn = 1;
 node[9]->apn = 2;
 node[10]->apn = 4;
 node[11]->apn = 7;
 node[11]->nextarc=NULL;
 
 strcpy(province[4].name,"甘肃");
 province[4].firstarc = node[12];
 node[12]->apn = 1;
 node[13]->apn = 3;
 node[14]->apn = 5;
 node[15]->apn = 6;
 node[16]->apn = 7;
 node[17]->apn = 9;
 node[17]->nextarc=NULL;
 
 strcpy(province[5].name,"内蒙古");
 province[5].firstarc = node[18];
 node[18]->apn = 4;
 node[19]->apn = 6; 
 node[20]->apn = 9;
 node[21]->apn = 13;
 node[22]->apn = 21;
 node[23]->apn = 32;
 node[24]->apn = 33;
 node[25]->apn = 34;
 node[25]->nextarc=NULL;
 
 strcpy(province[6].name,"宁夏");
 province[6].firstarc = node[26];
 node[26]->apn = 4;
 node[27]->apn = 5;
 node[28]->apn = 9;
 node[28]->nextarc=NULL;
 
 strcpy(province[7].name,"四川");
 province[7].firstarc = node[29];
 node[29]->apn = 2;
 node[30]->apn = 3;
 node[31]->apn = 4; 
 node[32]->apn = 8;
 node[33]->apn = 9;
 node[34]->apn = 10;
 node[35]->apn = 11;
 node[35]->nextarc=NULL;
 
 strcpy(province[8].name,"云南");
 province[8].firstarc = node[36];
 node[36]->apn = 2;
 node[37]->apn = 7;
 node[38]->apn = 11;
 node[39]->apn = 12;
 node[39]->nextarc=NULL;
 
    strcpy(province[9].name,"陕西");
 province[9].firstarc = node[40];
 node[40]->apn = 4;
 node[41]->apn = 5; 
 node[42]->apn = 6;
 node[43]->apn = 7;
 node[44]->apn = 10;
 node[45]->apn = 13;
 node[46]->apn = 14;
 node[47]->apn = 15;
 node[47]->nextarc=NULL;
 
 strcpy(province[10].name,"重庆");
 province[10].firstarc = node[48];
 node[48]->apn = 7;
 node[49]->apn = 9;
 node[50]->apn = 11;
 node[51]->apn = 15;
 node[52]->apn = 16;
 node[52]->nextarc=NULL;
 
 strcpy(province[11].name,"贵州");
 province[11].firstarc = node[53];
 node[53]->apn = 7;
 node[54]->apn = 8;
 node[55]->apn = 10;
 node[56]->apn = 12;
 node[57]->apn = 16;
 node[57]->nextarc=NULL;
 
 strcpy(province[12].name,"广西");
 province[12].firstarc = node[58];
 node[58]->apn = 8;
 node[59]->apn = 11;
 node[60]->apn = 16;
 node[61]->apn = 17;
 node[61]->nextarc=NULL;
 
 strcpy(province[13].name,"山西");
 province[13].firstarc = node[62];
 node[62]->apn = 5;
 node[63]->apn = 9;
 node[64]->apn = 14;
 node[65]->apn = 21;
 node[65]->nextarc=NULL;
 
 strcpy(province[14].name,"河南");
 province[14].firstarc = node[66];
 node[66]->apn = 9;
 node[67]->apn = 13;
 node[68]->apn = 15;
 node[69]->apn = 21;
 node[70]->apn = 24;
 node[71]->apn = 25;
 node[71]->nextarc=NULL;
 
 strcpy(province[15].name,"湖北");
 province[15].firstarc = node[73];
 node[73]->apn = 9;
 node[74]->apn = 10;
 node[75]->apn = 14;
 node[76]->apn = 16;
 node[77]->apn = 25;
 node[78]->apn = 26;
 node[78]->nextarc=NULL;
 
 strcpy(province[16].name,"湖南");
 province[16].firstarc = node[79];
 node[79]->apn = 10;
 node[80]->apn = 11;
 node[81]->apn = 12;
 node[82]->apn = 15;
 node[83]->apn = 17;
 node[84]->apn = 26;
 node[84]->nextarc=NULL;
 
 strcpy(province[17].name,"广东");
 province[17].firstarc = node[85];
 node[85]->apn = 12;
 node[86]->apn = 16;
 node[87]->apn = 19;
 node[88]->apn = 20;
 node[89]->apn = 26;
 node[90]->apn = 30;
 node[90]->nextarc=NULL;
 
 strcpy(province[18].name,"海南");
 province[18].firstarc = NULL;
 
 strcpy(province[19].name,"澳门");
 province[19].firstarc = node[91];
 node[91]->apn = 17;
 node[91]->nextarc=NULL;
 
 strcpy(province[20].name,"香港");
 province[20].firstarc = node[92];
 node[92]->apn = 17;
 node[92]->nextarc=NULL;
 
 strcpy(province[21].name,"河北");
 province[21].firstarc = node[93];
 node[93]->apn = 5;
 node[94]->apn = 13;
 node[95]->apn = 14;
 node[96]->apn = 22;
 node[97]->apn = 23;
 node[98]->apn = 24;
 node[99]->apn = 34;
 node[99]->nextarc=NULL;
 
 strcpy(province[22].name,"北京");
 province[22].firstarc = node[100];
 node[100]->apn = 21;
 node[101]->apn = 23;
 node[101]->nextarc=NULL;
 
 strcpy(province[23].name,"天津");
 province[23].firstarc = node[102];
 node[102]->apn = 21;
 node[103]->apn = 22;
 node[103]->nextarc=NULL;
 
 strcpy(province[24].name,"山东");
 province[24].firstarc = node[104];
 node[104]->apn = 14;
 node[105]->apn = 21;
 node[106]->apn = 25;
 node[107]->apn = 27;
 node[107]->nextarc=NULL;
 
 strcpy(province[25].name,"安徽");
 province[25].firstarc = node[108];
 node[108]->apn = 14;
 node[109]->apn = 15; 
 node[110]->apn = 24;
 node[111]->apn = 26;
 node[112]->apn = 27;
 node[113]->apn = 29;
 node[113]->nextarc=NULL;
 
 strcpy(province[26].name,"江西");
 province[26].firstarc = node[115];
 node[115]->apn = 15;
 node[116]->apn = 16;
 node[117]->apn = 17;
 node[118]->apn = 25;
 node[119]->apn = 29;
 node[120]->apn = 30;
 node[120]->nextarc=NULL;
 
 strcpy(province[27].name,"江苏");
 province[27].firstarc = node[122];
 node[122]->apn = 24;
 node[123]->apn = 25;
 node[124]->apn = 28;
 node[125]->apn = 29;
 node[125]->nextarc=NULL;
 
 strcpy(province[28].name,"上海");
 province[28].firstarc = node[126];
 node[126]->apn = 27;
 node[127]->apn = 29;
 node[127]->nextarc=NULL;
 
 strcpy(province[29].name,"浙江");
 province[29].firstarc = node[128];
 node[128]->apn = 17;
 node[129]->apn = 25;
 node[130]->apn = 26;
 node[131]->apn = 27;
 node[132]->apn = 28;
 node[132]->nextarc=NULL;
 
 strcpy(province[30].name,"福建");
 province[30].firstarc = node[133];
 node[133]->apn = 17;
 node[134]->apn = 26;
 node[135]->apn = 29;
 node[135]->nextarc=NULL;
 
 strcpy(province[31].name,"台湾");
 province[31].firstarc = NULL;
 
 strcpy(province[32].name,"黑龙江");
 province[32].firstarc = node[136];
 node[136]->apn = 5;
 node[137]->apn = 33;
 node[137]->nextarc=NULL;
 
 strcpy(province[33].name,"吉林");
 province[33].firstarc = node[138];
 node[138]->apn = 5;
 node[139]->apn = 32;
 node[140]->apn = 34;
 node[140]->nextarc=NULL;
 
 strcpy(province[34].name,"辽宁");
 province[34].firstarc = node[141];
 node[141]->apn = 5;
 node[142]->apn = 21;
 node[143]->apn = 33;
 node[143]->nextarc=NULL;
}
void Initialization(VNode*province){
 for (int i = 1; i <= 34; i++)  
  {
  province[i].color = 0; 
  province[i].number=i;
  for(int j=0;j<5;j++)
  color[i][j]=j+1;
  }
}

void CreateListR(DLinkNode *&L,VNode*province,int n){
 DLinkNode *s,*r;
 L=(DLinkNode *)malloc(sizeof(DLinkNode));   //创建头结点
 L->prior=L->next=NULL;
 L->data=&province[1];
 r=L;     //r始终指向终端结点,开始时指向头结点
 for (int i=2;i<=n;i++)
 { 
  s=(DLinkNode *)malloc(sizeof(DLinkNode));//创建新结点
  s->data=&province[i];
  r->next=s;s->prior=r; //将结点s插入结点r之后
  r=s;
 }
 r->next=L;    //尾结点next域置为头节点
 L->prior=r;
}


void Painting(VNode*province,ArcNode*p,int i){
 p = province[i].firstarc;
 //将相邻省已用颜色赋值为0
 while(p!=NULL)
 {
  switch(province[p->apn].color)
  {
   case 1:color[i][0]=0;break;
   case 2:color[i][1]=0;break;
   case 3:color[i][2]=0;break;
   case 4:color[i][3]=0;break;
   case 5:color[i][4]=0;break;
   default:break;
  }
  p = p->nextarc;
 }
 //将第一个不为0颜色值赋给当前省份
 for(int j=0;j<5;j++)
 {
  if(color[i][j]!=0)
  {  
      province[i].color =color[i][j];
      color[i][j]=0;
      break;
  }
    }  
}

void Setcolor(int i){
 HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
 switch (i)
      {
          case 1:SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_GREEN); break;//绿色
          case 2:SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN); break;//黄色
          case 3:SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED); break;//红色
           case 4:SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_BLUE); break;//蓝色
          case 5:SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE);break;//紫色
          case 6:SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE);break;//浅蓝
          case 7:SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);break;//白色
          case 8:SetConsoleTextAttribute(handle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);break;//默认低亮白色
         }

void Output(VNode*province,ArcNode*p){
 printf("\n中国34个省份颜色如下:\n");
 for(int i=1;i<=34;i++)
 {
  Setcolor(province[i].color);
  printf("%d %s\t", i,province[i].name);
  if(i%12==0)
  printf("\n");
 }
 Setcolor(8);
 printf("\n\n");
   printf("\n中国34个省份颜色及其各邻接省份颜色如下请查阅:\n");
    for(int j=1;j<=7;j++)
 {
  for(int i=1;i<= 34;i++)  
      if(province[i].color==j)
      {
    Setcolor(province[i].color);
      printf("%d\t%s\t",i,province[i].name);
     Setcolor(8);
      printf("邻接省份有:");
      p = province[i].firstarc;
      while (p != NULL)
       {
        Setcolor(province[p->apn].color);
      printf("%s  ",province[p->apn].name);
      p = p->nextarc;
       }
   printf("\n");
      }
  printf("\n");
 }
 Setcolor(8)
}

void Find(DLinkNode *&L,VNode*province,ArcNode*p){
   DLinkNode *r=L,*s;
   int Maxcolor=2,Mincolor=5;
      do
   {
   s=r;
   Maxcolor=2;
   Initialization(province);
   while(s!=s->prior)
   {
   Painting(province,p,s->data->number);
   if(s->data->color>Maxcolor)
   if(s->data->number!=r->data->number)
   {
    s->data->color=0;
    for(int j=0;j<5;j++)
    color[s->data->number][j]=j+1;
    s=s->prior;
    goto a;
   }
      else  
      {
       printf("从第%d个省%s开始着色用%d种颜色着色失败\n",r->data->number,r->data->name,Maxcolor);
          Maxcolor++;
          Initialization(province);
          s=r;
          goto a;
   }
   if(s->data->number==r->prior->data->number)     
   {
    printf("从第%d个省%s开始着色用%d种颜色着色成功",r->data->number,r->data->name,Maxcolor);
    if(Maxcolor<Mincolor)Mincolor=Maxcolor;
    Output(province,p);
    goto b;
   }
    s=s->next;
    a:;
   }
        b:r=r->next;
  }while(r!=L);
  Setcolor(4);
  printf("\n对中国地图最少着色颜色数为%d种!!",Mincolor);
  Setcolor(8);
  return;
}
结果为最少用4种颜色才能对中国地图着色,其实显然两种和三种是不可能成功的,问题本质上就是在中国地图上验证了四色定理。在选择数据结构时我为了节省存储空间采用了邻接表,读者也可以使用邻接矩阵,在中国地图的数据输入时比较方便。
  • 22
    点赞
  • 106
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值