图着色--非递归实现

图着色递归版,请移步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;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值