- 問題描述
問題描述:地圖四色着色
給已知的地圖(比如中國地圖)着色,請設計地圖着色軟件,對個區域(各省)進行着色,要求相鄰區域(省)所使用的顏色不同,並保證使用的顏色最少(最少是四色)。
- 設計思路
設計思路:
數據結構的設計:地圖可以採用圖的數據結構,每個省爲一個節點,邊表示對應的兩個省相鄰。
算法設計:設計着色算法,保證鄰接點不是同一種顏色。
算法實現:
初始狀態:集合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;
}