欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

七巧板的四色问题

程序员文章站 2022-03-03 11:20:48
...

学习了数据结构图的相关知识后,实验是实现DFS,BFS算法,并且输出七巧板四色问题的所有方案
七巧板的四色问题这样一个图的邻接矩阵为七巧板的四色问题

首先是类的定义

因为七巧板的图相对比较稀疏,所以用无向图的邻接表存储

struct Edge {
	int adjvex;	//邻接顶点的序号
	Edge* next;	//下一个邻接点
};
enum Color {red, yellow, blue, green, white};
struct Vertex {
	char VertexName;	//顶点名
	Color color = white;	//默认是白色
	Edge* firstedge;	//边结点
};
class Graph {
private:
	Vertex* vertexlist;	//创建对象时动态分配存储顶点的数组
	int vertexNum;	int edgeNum;	//顶点数和边数
	bool* visited;	//记录是否访问过
	int num = 0;	//涂色方案数
public:
	Graph(int n, int e);	//分别是顶点数和边数
	~Graph();
	void initialise();	//初始化
	void DFS(int v);	//深度优先遍历输出各顶点及其颜色
	void BFS();	//广度优先遍历输出各顶点及其颜色
	bool conficting(int v);	//顶点v的颜色与其相邻边是否冲突(没有边视为不冲突)
	void coloring(int v);	//涂色
	void printMatrix();	//输出邻接矩阵
};

然后是类函数的实现。

Graph::Graph(int n, int e) {
	vertexNum = n; edgeNum = e;
	vertexlist = new Vertex[vertexNum];
	visited = new bool[vertexNum];
	for (int i = 0; i < vertexNum; i++) {
		vertexlist[i].VertexName = 'A' + i;	//从A开始依次命名顶点
		vertexlist[i].firstedge = nullptr;
	}
	cout << "依次输入每个边依附顶点的序号" << endl;
	int a, b;
	for (int i = 0; i < 2 * e; i++) {
		cin >> a >> b;
		Edge* s = new Edge;
		s->adjvex = b;
		s->next = vertexlist[a].firstedge;	//插入边结点
		vertexlist[a].firstedge = s;
	}
}
Graph::~Graph() {
	Edge* cur = nullptr;
	for (int i = 0; i < vertexNum; i++) {
		Edge* p = vertexlist[i].firstedge;
		if (p == nullptr)
			continue;	//如果没有边则跳过该顶点
		cur = p->next;
		while (cur != nullptr) {
			delete p;
			p = cur;
			cur = cur->next;
		}
		delete p;
	}
	delete[] visited;
	delete[] vertexlist;
}
void Graph::initialise() {
	num = 0;
	for (int i = 0; i < vertexNum; i++) {
		visited[i] = false;
		vertexlist[i].color = white;
	}
}
void Graph::DFS(int v) {
	if (!visited[v]) {
		cout << vertexlist[v].VertexName << " ";
		switch (vertexlist[v].color) {
			case red: cout << "红色\n";	break;
			case yellow: cout << "黄色\n";	break;
			case blue: cout << "蓝色\n";	break;
			case green: cout << "绿色\n"; break;
			default: cout << "白色\n";	break;
		}
		visited[v] = true;
	}
	Edge* p = vertexlist[v].firstedge;
	int j = 0;
	while (p != nullptr) {
		j = p->adjvex;
		if (!visited[j])
			DFS(j);
		p = p->next;
	}
}
void Graph::BFS() {
	Edge* p;
	int j;
	for (int i = 0; i < vertexNum; i++) {
		if (!visited[i]) {
			cout << vertexlist[i].VertexName << " ";
			switch (vertexlist[i].color) {
				case red: cout << "红色\n";	break;
				case yellow: cout << "黄色\n";	break;
				case blue: cout << "蓝色\n";	break;
				case green: cout << "绿色\n"; break;
				default: cout << "白色\n";	break;
			}
			visited[i] = true;
		}
		p = vertexlist[i].firstedge;
		while (p != nullptr) {
			j = p->adjvex;
			if (!visited[j]) {
				cout << vertexlist[j].VertexName << " ";
				switch (vertexlist[j].color) {
					case red: cout << "红色\n";	break;
					case yellow: cout << "黄色\n";	break;
					case blue: cout << "蓝色\n";	break;
					case green: cout << "绿色\n"; break;
					default: cout << "白色\n";	break;
				}
				visited[j] = true;
			}
			p = p->next;
		}
	}
}
bool Graph::conficting(int v) {
	Edge* p = vertexlist[v].firstedge;
	if (p == nullptr)
		return false;
	else {
		while (p != nullptr) {
			if (vertexlist[v].color == vertexlist[p->adjvex].color)
				return true;
			p = p->next;
		}
		return false;
	}
}
void Graph::coloring(int v) {
	if (v >= vertexNum) {
		cout << "第" << ++num << "种方案:" << endl;
		for (int i = 0; i < vertexNum; i++) {
			cout << vertexlist[i].VertexName << "涂";
			switch (vertexlist[i].color) {
				case red: cout << "红色\n";	break;
				case yellow: cout << "黄色\n";	break;
				case blue: cout << "蓝色\n";	break;
				case green: cout << "绿色\n"; break;
			}
		}
	}
	else {
		//依次尝试4种颜色
		for (int i = 0; i < 4; i++) {
			vertexlist[v].color = (Color)i;
			if (conficting(v))	//颜色冲突,试下一种颜色
				continue;
			else	//颜色不冲突或没有边
				coloring(v+1);
		}
	}
	//所有颜色都冲突时,取消涂色并回溯
	vertexlist[v].color = white;
}
void Graph::printMatrix() {
	//用动态二维数组存储邻接矩阵
	bool** matrix = new bool*[vertexNum];
	for (int i = 0; i < vertexNum; i++)
		matrix[i] = new bool[vertexNum];
	//初始化为0
	for(int i = 0; i < vertexNum; i++)
		for (int j = 0; j < vertexNum; j++) {
			matrix[i][j] = 0;
		}
	//有边的点改为1
	Edge* p;
	for (int i = 0; i < vertexNum; i++) {
		p = vertexlist[i].firstedge;
		while (p != nullptr) {
			matrix[i][p->adjvex] = 1;
			p = p->next;
		}
	}
	//输出
	cout << "邻接矩阵为:" << endl;
	for (int i = 0; i < vertexNum; i++) {
		for (int j = 0; j < vertexNum; j++) {
			cout << matrix[i][j] << "  ";
		}
		cout << endl;
	}
	//释放空间
	for (int i = 0; i < vertexNum; i++)
		delete[] matrix[i];
	delete[] matrix;
}

共有672种涂色方案,输出结果为
七巧板的四色问题

最后析构时,Visio studio在delete[] vertexlist处会触发一个断点,导致不能正常结束程序
七巧板的四色问题
但试其他图时没有该问题,不知道是什么原因。

相关标签: 数据结构 算法