一、 问题描述
任何平面区域图都可以用四种颜色着色,使相邻区域颜色互异。这就是四色定理。要求给定区域图,排出全部可能的着色方案。例如,区域图如下图所示:
要求用四种颜色着色。
则输入: 10 4 (分别表示区域数和颜色数)
0 1 0 0 0 0 0 0 0 0 1 0 1 1 1 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 1 1 0 1 1 1 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 1 0 0 1 0 1 0 0 0 0 1 1 1 0 1 1 1 0 0 0 0 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 1 1 1 0
输出结果为:1584
二、算法思想
这个问题可以使用回溯法来解决。我们可以使用一个列表来记录每个区域的颜色,初始时所有区域都没有着色。然后从第一个区域开始,尝试给它着色,并检查是否满足相邻区域颜色互异的条件。如果满足条件,则继续下一个区域的着色,直到所有区域都着色完成。如果不满足条件,则回溯到上一个区域,尝试其他颜色。
三、代码实现
#include <stdio.h>
#include <stdbool.h>
#define MAXN 10
int graph[MAXN][MAXN]; // 区域图
int colors[MAXN]; // 存储每个区域的颜色
int n, m; // 区域数和颜色数
int count = 0; // 方案数
// 检查某种颜色是否可以用于某个区域
bool isSafe(int v, int c) {
for (int i = 0; i < n; i++) {
if (graph[v][i] && c == colors[i]) {
return false;
}
}
return true;
}
// 递归函数,尝试为每个区域选择颜色
void graphColoring(int v) {
if (v == n) {
count++;
return;
}
for (int c = 0; c < m; c++) {
if (isSafe(v, c)) {
colors[v] = c;
graphColoring(v + 1);
colors[v] = -1; // 回溯
}
}
}
int main() {
scanf("%d %d", &n, &m);
// 读取区域图
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &graph[i][j]);
}
}
// 初始化颜色数组
for (int i = 0; i < n; i++) {
colors[i] = -1;
}
// 开始递归着色
graphColoring(0);
printf("%d\n", count);
return 0;
}
执行结果
结语
创造机会的人是勇者
等待机会的是愚者
!!!