回溯演算法---四色圖著色
回溯演算法基本思想:
判斷第一個節點的各個候選值{ //當無未進行判斷的候選者時,則退出
當將某候選值賦予第一個節點時,判斷此時是否存在一個解路徑。
若不存在,則繼續判斷下一個候選值。
}
具體演算法思想如下:
NUM : 解路徑上節點的個數 CANDIDATA_NUM: 每個節點的候選值的個數 |
BOOL TestNode(I,j) 判斷當將候選值j賦予節點i時,是否能找到一條解路徑 |
//是否有解 BOOL Find() { BOOL bExist=FALSE; //從起始節點的候選值依次判斷 For(int j=0; j<CANDIDATA_NUM;j++) { IF(TestNode(0,j)) { bExist=True; } } Return bExist; } |
四色圖問題:
設有下圖所示地圖,每個區域代表一個省,區域中的數字代表省的編號,今將每個省塗上紅(R),蘭(B),黃(Y),綠(G)四種顏色之一,使相鄰的省份有不同的顏色。
演算法說明:
這是一道非常典型的回溯題目。解法與“八皇后問題”一樣。在填寫每一個省的顏色時檢查與相鄰已填省份的顏色是否相同。如果不同,則填上;如果相同(衝突),則另選一種;如果已沒有顏色可供選擇,則回溯到上一省份。重複這一過程,直到所有省的顏色都已填上。
最主要的問題在於如何解決相鄰省的顏色衝突。對每一個省份,可供選擇的顏色一共有四種;對省份i來說顏色x可填的條件是編號為1~(i-1)且與省i相鄰的省份的顏色都不是x。
各省之間的相鄰關係用矩陣R(n,n)來表示:
r(i,j)=1或0 1:表示相鄰 0表示不相鄰
本題的相鄰矩陣如下:
0 |
1 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
0 |
1 |
1 |
1 |
0 |
1 |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
1 |
1 |
1 |
0 |
0 |
0 |
1 |
0 |
主要函式:
int r[7][7]=
{
{0,1,0,0,0,0,1},
{1,0,1,1,1,1,1},
{0,1,0,1,0,0,0},
{0,1,1,0,1,0,0},
{0,1,0,1,0,1,1},
{0,1,0,0,1,0,1},
{1,1,0,0,1,1,0}
};
BOOL CGraphicDlg::TestNode(int i,int j)
{
// 判斷 i行j列 是否滿足條件
//與之前的行相比
for (int k=0;k<=i-1;k++)
{
//與第K區域相鄰
if(r[i][k]==1)
if (A[k]==j)
return FALSE;
}
A[i]=j;
// 到此為止 0--i行 均無衝突
// 如果是最後一行 成功找到一個解 將其加如到總解中
if(i==NUM-1){
OneResult.clear();
for (int k1=0;k1<NUM;k1++)
{
OneResult.push_back(A[k1]);
}
AllResuleVec.push_back(OneResult);
return TRUE;
}
//如果不是最後一行 則判斷i+1行
// 判斷 i+1行 是否存在不衝突的解
BOOL bSuit=FALSE;
for (int k=0;k<ColorNum;k++)
{
//第i+1行存在合適位置
if (TestNode(i+1,k))
{
bSuit=TRUE;
//如果找到合適的 直接退出
//break;
}
}
return bSuit;
}
BOOL CGraphicDlg::ColorGraphic()
{
AllResuleVec.clear();
OneResult.clear();
BOOL bExit=FALSE;
for (int j=0;j<ColorNum;j++)
{
if (TestNode(0,j))
{
bExit=TRUE;
}
}
return bExit;
}
經測試,此圖共有192中著色方案, 示例如下:
測試程式: