图着色递归版,请移步http://blog.csdn.net/jiangxi756/article/details/21338619。
通过前面的递归办很容易验证当前代码是否正确。
不管是迭代版还是非迭代版本。俩者都是通过递归树来转化。理解好递归树是问题的关键。
递归树的的树枝个人认为是行为,而节点是来着行为的结果。
对于非递归版本,需找到
1 退出条件
2 选用满足要求的情况,进入下一行为
3 得到结果进行下一节点的条件检查!(1 继续下一节点遍历 2 达到树底 3 当前层分支情况都遍历完,需回溯!并且1,2可归在一起,3为另一种情况.)
以上的步骤均在代码中有标注!
以上分析均个人分析,写代码的经验总结。如有不妥欢迎留言。谢谢。
#include <iostream>
using namespace std;
//图的描述邻接矩阵
bool is_ok(int A[][4],int n,int level,int c[]);
int trace_back(int A[][4],int n,int level,int c[],int m,int &total);
int color_graph(int A[][4],int n,int c[],int m);
bool is_ok(int A[][4],int n,int level,int c[]);
int main()
{
int A[4][4]={{0,1,1 ,0},{1,0,1,1},{1,1,0,1},{0,1,1,0}};
int c[4]={0,0,0,0};
int count(0);
int m_color;
char control_c;
//获取最优解
for(int count_i = 1;count_i <= 4;count_i++)
{
m_color = count_i;
count = color_graph(A,4,c,m_color);
if (count > 0)
{
cout<< "find the least color num!"<<endl;
cout<< "color num:"<<m_color<<endl;
break;
}
}
cout<<"---------------------------"<<endl;
//以下用于验证
do
{
count = 0;
m_color = 0;
cout<<"color num:";
cin>>m_color;
count = color_graph(A,4,c,m_color);
cout<<"total:"<<count<<endl;
cout<<"y?n :";
cin>>control_c;
}while (control_c != 'n' && control_c != 'N');
return 1;
}
bool is_ok(int A[][4],int n,int level,int c[])
{
for (int i = 0;i < n;i++ )
{
if (A[level][i] == 1&& c[i] ==c[level] )//邻接点颜色相同为假
{
return false;
}
}
return true;
}
// m为颜色种数
int color_graph(int A[][4],int n,int c[],int m)
{
//初始化相应的变量,最忌讳未初始化就用--,++操作,结果未定义
int level(0);
int total(0);
while(level >= 0)//1 退出条件
{
c[level] = c[level] + 1;//先选一种颜色
for (;c[level] <= m ; c[level]++)//2 行为
{
if (is_ok(A,n,level,c))break;//合适就不用继续选颜色,直接退出否则,继续遍历的试。
}
// 以上是选择一个合适的颜色
//3 下面则是选择颜色后,就选择的节点做相应的下一步操作
if(c[level] <= m)//表示仍有可选的颜色
{
//表示每个节点均与遍历
if(level == n-1)//注意下标!
{
total++;
for(int i = 0; i < n;i++)
{
cout<<" "<<c[i]<<" ";
}
cout<<endl;
}
else//节点未遍历完
{
level++;//继续下一个节点
}
}
else//大于可供选择的颜色则需回溯
{
c[level] = 0;//清除以前的痕迹,为回溯准备
level--;
}
}
return total;
}