- 问题描述
问题描述:地图四色着色
给已知的地图(比如中国地图)着色,请设计地图着色软件,对个区域(各省)进行着色,要求相邻区域(省)所使用的颜色不同,并保证使用的颜色最少(最少是四色)。
- 设计思路
设计思路:
数据结构的设计:地图可以采用图的数据结构,每个省为一个节点,边表示对应的两个省相邻。
算法设计:设计着色算法,保证邻接点不是同一种颜色。
算法实现:
初始状态:集合A元素放入cq中,Result及newr置零,设置组号group=1,group1,2,3,4分别代表颜色红色,蓝色,黄色,绿色。
当第1个元素出队时。将R矩阵中第1行元素中的“1”拷入newr向量对应位置;凡是与第一元素有冲突的元素处均置为“1”。这里说明序号为2的元素不能进入第一组,则应将元素2出队后重新入cq的队尾。继续将元素3出队,并将R矩阵中第三行元素中的“1”拷入newr向量对应位置;如此继续,直到9个元素依次出队后,由newr单元中为“0”的单元序号构成第1组,将“1”标志放入Result向量对应单元中;将group=2,newr清零,重新对cq中剩余的元素重复上述操作,可得第2组元素,第3组元素……直到cq中front=rear,队空,运算结束。
数据结构:
n——区域(省份)个数;
m——为着色数4
a[n][n]为邻接矩阵。
循环队列cq[0:n-1],存放集合a的元素;
数组Result[1:n]用以存放每个元素的分组号;
newr[1:n]为工作数组。
算法描述:
MAP COLORING(R, n, cq, newr, Result)
- Input(n,a[n][n])//输入区域个数及其邻接情况//
- FOR k=0 TO n-1 cq[k]←k+1; //n个元素存入循环队列cq//
- front←n-1; rear←n-1; //头尾指针赋初值//
- FOR K=1 TO n newr[k]←0 //newr向量置初值//
- group←1; pre←0; //group为当前组号,pre为前一个出队元素编号,初值为零//(pre←9);
- fi=.t.
- WHILE rear≠front.or.fi=.t. DO //队列非空//
- Fi=.f.
- front←front+1; IF front=n+1 THEN front←1;
- I←cq[front]; //I为当前出队元素//
- IF I<pre
- THEN //重新开辟新组//
- group←group+1; Result[I]←group; //记录组号//
- FOR k=1 TO n newr[k]←R[I, k]
- ELSE
- IF newr[I]≠0
- THEN //发生冲突元素,重新入队//
- rear=rear+1; IF rear=n+1 THEN rear=1;
- cq[rear]←I
- ELSE //可以分在当前组//
- Result[I]←group;
- FOR k=1 TO n
- Newr[k]←newr[k]+R[I, k];
- pre←I
- END(WHILE)
- Output(result)
- 测试用例及结果说明
测试用例:
区域个数n=9;
各个区域的接壤情况为:
第1组相邻区域编号为:1,2
第2组相邻区域编号为:2,3
第3组相邻区域编号为:3,4
第4组相邻区域编号为:4,5
第5组相邻区域编号为:5,6
第6组相邻区域编号为:6,7
第7组相邻区域编号为:7,8
第8组相邻区域编号为:8,9
第9组相邻区域编号为:1,3
第10组相邻区域编号为:1,4
第11组相邻区域编号为:1,5
地图组成的邻接矩阵为:
0 1 1 1 1 0 0 0 0
1 0 1 0 0 0 0 0 0
1 1 0 1 0 0 0 0 0
1 0 1 0 1 0 0 0 0
1 0 0 1 0 1 0 0 0
0 0 0 0 1 0 1 0 0
0 0 0 0 0 1 0 1 0
0 0 0 0 0 0 1 0 1
0 0 0 0 0 0 0 1 0
着色结果为:
区域1为红色
区域2为蓝色
区域3为黄色
区域4为蓝色
区域5为黄色
区域6为红色
区域7为蓝色
区域8为红色
区域9为蓝色
- 设计及测试过程
第一步:提出问题;
第二步:问题转换;
第三步:算法构思;
第四步:伪码描述;
第五步:代码编写;
第六步:代码测试;
第七步:代码修正;
参考书籍:《计算机软件技术基础》 清华大学出版社 第三版
#include <iostream>
using namespace std;
#define N 64
int main()
{
int a[N][N], i, j, k, n, b, c, d, e, f, cq[N], result[N], newr[N], front, rear, group, pre;
for(i=0;i<N;i++)
for(j=0;j<N;j++)
a[i][j]=0;
cout<<"请输入地图区域个数"<<endl;
cin>>n;
cout<<"各区域编号分别为:"<<endl;
for(i=0;i<n;i++)
cout<<i+1<<", ";
cout<<"请输入各个区域的接壤情况(结束输入请输入'0')"<<endl;
i=0;
while(1)
{
cout<<"第"<<i+1<<"组相邻区域编号为:"<<endl;
cin>>b;
if(b==0)
break;
cin>>c;
a[b-1][c-1]=1;
a[c-1][b-1]=1;
i++;
}
cout<<"地图组成的邻接矩阵为:"<<endl;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
cout<<a[i][j]<<" ";
cout<<endl;
}
for(i=0;i<N;i++)
cq[i]=i+1;
front=N-1;
rear=N-1;
for(i=0;i<N;i++)
newr[i]=0;
group=1;
pre=0;
f=0;
while(rear!=front||f==0)
{
f=1;
front=(front+1)%N;
i=cq[front];
if(i<pre)
{
group++;
result[i-1]=group;
for(j=0;j<N;j++)
newr[j]=a[i-1][j];
}
else
{
if(newr[i-1]!=0)
{
rear=(rear+1)%N;
cq[rear]=i;
}
else
{
result[i-1]=group;
for(j=0;j<N;j++)
newr[j]=newr[j]+a[i-1][j];
}
}
pre=i;
}
cout<<"着色结果为:"<<endl;
for(i=0;i<n;i++)
{
if(result[i]==1)
cout<<"区域"<<i+1<<"为红色"<<endl;
if(result[i]==2)
cout<<"区域"<<i+1<<"为蓝色"<<endl;
if(result[i]==3)
cout<<"区域"<<i+1<<"为黄色"<<endl;
if(result[i]==4)
cout<<"区域"<<i+1<<"为绿色"<<endl;
}
system("pause");
return 0;
}