回溯法解决图着色问题

 

复制代码
#include<iostream>
using namespace std;
int G[50][50];   //保存无向图
int color[50];   //存放每个点的颜色 
int sum = 0;   //需要的颜色总数 
int mins = 999999;   //需要的最少的颜色数
int N;   //点的总个数 
//检查点第i+1个点是否能放颜色c
bool check(int i, int c) {
    bool flag = true;
    for (int j = 0; j < i; j++) {
        if (G[j][i] == 1) {  //前面与第i+1个点直接相连的点 
            if (color[j] == c)   //相连的点有颜色c 
                flag = false;
        }
    }
    return flag;
}
//问题求解 
void dfs(int i) {
    if (i > N - 1) {   //递归出口 
        if (sum < mins)
            mins = sum;   //记录最小颜色数 
        return; //有没有这句都一样,因为函数会自动返回(执行完函数体所有语句就返回)
    }
    else {
        //对第i+1个结点,尝试已使用的所有颜色
        int findColor = 0;  //标记能否在已有颜色中找到可以使用的颜色 
        for (int j = 0; j < sum; j++) {
            if (check(i, color[j])) {  //如果颜色冲突,直接执行下一次for循环,不做任何操作(剪枝)
                findColor = 1;  //只要已有的颜色中有不冲突的,findColor就会被置为1
                int sum1 = sum;  //sum1是一个临时变量,记录了这次递归的颜色总数
                color[i] = color[j];   //第i+1个点和第j+1个点颜色相同 
                dfs(i + 1);        //在这个颜色满足条件的情况下,记录好这个颜色,然后求下一个点的颜色 
                sum = sum1;   //回溯,(执行下一次for循环时,颜色总数应该不变,所以要回置颜色数)
            }
        }
        if (findColor == 0) {   //已有的颜色都不能用,已经走完了所有的颜色,所以不用回溯,而是去求下一个顶点的颜色
            sum++;   //总颜色数加一 
            color[i] = sum;
            dfs(i + 1);   //求下一个点的颜色 
        }
    }
}
int main() {
    cout << "请输入点的总个数" << endl;
    cin >> N;
    cout << "请输入二维矩阵表示的边的连接情况(1表示有边相连,0表示没有边相连)" << endl;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            cin >> G[i][j];
        }
    }
    dfs(0);
    cout << "最少颜色数: " << mins << endl;
    system("pause");
}
/*
* 
0 1 1 0 0
1 0 1 1 1
1 1 0 0 1
0 1 0 0 1
0 1 1 1 0
*/
复制代码

 

posted @   Jocelynn  阅读(116)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示