回溯法(2)--图着色问题和旅行商问题

news2024/11/19 23:37:26

目录

一、图着色问题

1、算法设计

2、代码

二、旅行商问题 

1、概述问题

2、穷举法

3、回溯法 


一、图着色问题

1、算法设计

        图着色问题,给定图中各个区域的相邻关系,抽象成一个无向图G=(V,E),给定m种颜色,可以选择一个颜色可以对每一个区域(无向图的顶点)进行着色,但需要保证相邻区域之间不能颜色相同,如下图的无向图表示。

        无向图采用建立邻接矩阵a[ ][ ]来表示。注意:i和j都是从1开始的,而不是0开始的,所以邻接矩阵的0行0列,设定为-1,表示不存在。

                a[i][j]=\left\{\begin{matrix} 1 \qquad (i,j)\in E\\ 0 \qquad \quad others \end{matrix}\right. 

         算法:回溯法,子集树方法。

        backtrack回溯过程:

(1)首先判断是否叶子结点已经搜索,即t>n,若满足条件,则输出当前着色方法,sum++。

(2)若不满足条件,则在当前层遍历m种颜色,若该颜色满足扩展条件,则扩展该叶子结点搜索下一层,否则选择下一个颜色,直到所有颜色都不满足条件则回溯上一层。

(3)扩展条件:遍历n个结点,若结点与叶子结点有相邻关系a[t][i]==1且叶子结点和该遍历的结点颜色相同x[t]==x[i],则返回false,否则存在一个结点有相邻关系且颜色不同,返回true用来做新的扩展结点。

(4)另外,判断(t<=n)&&x[t]==m,如果当前层数不在叶子结点层(第n层),且该层修改的颜色值为最后一个颜色(由于颜色按顺序遍历),则颜色置0,退出当前迭代层,返回上一层。也就是说当前叶子结点的所有子树都搜索过了,该结点变为死结点,要么返回到该叶子结点的邻树,要么返回叶结点上一层。

2、代码

//图着色问题
public class graphcoloration {
    static int n=5;          //顶点数
    static int m=3;          //颜色数
    static int a[][]={         //邻接矩阵
        {-1,-1,-1,-1,-1,-1},
        {-1,0,1,1,1,0},
        {-1,1,0,1,0,1},
        {-1,1,1,0,1,1},
        {-1,1,0,1,0,1},
        {-1,0,1,1,1,0}
    };   //-1是不存在0点,0是不可达
    static int sum=0;                   //可行解
    public static void main(String[] args)
   {
        int x[]=new int[n+1];           //x存储可达的路线
        backtrack(1, x);                //初始节点在第一层
        System.out.println(sum);        //输出有多少种可行解
   }
   public static void backtrack(int t,int x[])
   {
        if(t>n)
        {    
            sum++;
            for(int i=1;i<=n;i++)
            {
                System.out.print(x[i]+" ");
            }
            System.out.println();
        }
        
        else{
            for(int i=1;i<=m;i++)
            {
                x[t]=i;
                if(OK(t,x))                       //如果满足扩展条件则扩展
                    backtrack(t+1, x);
                if((t<=n)&&x[t]==m)               //如果当前层数不在叶子结点,且该层修改的数为最后一个颜色,则颜色置0,退出当前迭代层                              
                {   
                    x[t]=0;
                    break;
                }
                
            }
        }
   }
   public static boolean OK(int t,int x[])
   {
        for(int i=1;i<=n;i++)
        {
            if((a[t][i]==1)&&x[t]==x[i])        //判断所有相邻关系中颜色相同的返回false
                return false;
        }
        return true;                            //留下的都是存在相邻关系且颜色不同的返回true
   }
} 
   

二、旅行商问题 

1、概述问题

        一个旅行商希望从一个城市出发访问n个城市,每个城市只能访问一次,且开始和结束在同一城市,给出一个不同城市之间距离的加权完全图,请设计一个算法,找到旅行商的最短路径。也就是图论中的求出最小的哈密顿回路。

        下面的算法依照下图为例,出发为a点。

2、穷举法

        穷举法就是求所有a为出发点,a为终点的全排列。

        全排列算法:

(1)全排列算法使用递归算法,如果迭代到最后一层,则计算当前路线的加权和(注意第一个值不用进行全排列,因为初始点不动),minl存放加权和最小的值。

(2)若没有迭代到最后一层,则遍历k<=i<=n,k为当前全排列迭代的层数,交换op[i]和op[k],继续排列k+1层,再交换op[i]和op[k],保证对后续没有影响。

代码如下:

//旅行商问题
public class tsp {
   public static final int MAX=9999;
   public static int[][] a={
    {MAX,MAX,MAX,MAX,MAX},
    {MAX,MAX,2,5,8},
    {MAX,2,MAX,7,3},
    {MAX,5,7,MAX,1},
    {MAX,8,3,1,MAX},
   };
   public static int n=4;
   public static int minl=999;
   public static void main(String []args)
   {
        int op[]=new int[n+1];
        for(int i=1;i<=n;i++)
            op[i]=i;
        perm(2,op);
        System.out.println(minl);
   } 

   //全排列算法
   public static void perm(int k,int op[])
   {
        if(k==n)
        {  
            int tmp=calulate(op);
            minl=tmp<minl?tmp:minl;
        }
        for(int i=k;i<=n;i++)
        {
            swap(i,k,op);
            perm(k+1,op);
            swap(i,k,op);
        }
   }

   //交换数组中元素
   public static void swap(int i,int k,int []op)
   {
        int tmp=op[i];
        op[i]=op[k];
        op[k]=tmp;
   }

   //计算全排列后当前排列的加权和
   public static int calulate(int []op)
   {
        int tot=0;
        for(int i=1;i<n;i++)
        {
            tot+=a[op[i]][op[i+1]];
        }
        tot+=a[op[n]][1];
        return tot;
   }
}

3、回溯法 

        时间复杂度分析:对于回溯法(本质上也是穷举法)和穷举法的时间复杂度都是O(n!),所以随着城市的数量增加,计算时间指数级增长,所以对于大规模的TSP问题可以采用动态规划、启发式算法等方法,来在短时间接近最优解,但这一定不是完备的。

        算法流程:

(1)首先判断是否叶子结点已经搜索,即满足k>n,则计算当前加权和,minl保存最小的加权和。

(2)若不满足,则遍历所有叶子结点,是否存在可以扩展的结点,进行扩展迭代到下一层,若没有则返回上一层。

(3)扩展条件:判断所有结点中满足a[k][i]!=MAX即待扩展节点与判断结点不可达,且x[k]==x[i]待扩展节点与判断结点相同,则不可扩展。也就是存在某一节点可以到达,且与上一个结点不同,则扩展。

//旅行商问题
public class tsp {
   public static final int MAX=9999;
   public static int[][] a={
    {MAX,MAX,MAX,MAX,MAX},
    {MAX,MAX,2,5,8},
    {MAX,2,MAX,7,3},
    {MAX,5,7,MAX,1},
    {MAX,8,3,1,MAX},
   };
   public static int n=4;
   public static int minl=999;
   public static void main(String []args)
   {
        int op[]=new int[n+1];
        int x[]=new int[n+1];
        for(int i=1;i<=n;i++)
            op[i]=i;
        backtrack(1,x);
        System.out.println(minl);
   } 
   //回溯法
   public static void backtrack(int k,int x[])
   {
        //注意这里一定要大于号,也就是已经判断好当前路径的叶子结点,再进行输出,或者替换最小值。
        if(k>n)
        {
            int tot=0;
            for(int i=1;i<n;i++)
                 tot+=a[x[i]][x[i+1]]; 
            tot+=a[x[n]][x[1]];
            minl=minl<tot?minl:tot;
        }
        else
        {
            for(int i=1;i<=n;i++)
            {
                x[k]=i;
                if(Ok(k, x))
                    backtrack(k+1,x);
            }
        }
   }
   //判断是否能继续扩展
   public static boolean Ok(int k,int x[])
   {
        for(int i=1;i<=n;i++)
        {
            if(a[k][i]!=MAX&&x[k]==x[i])
                return false;
        }
        return true;
   }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1155011.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【HarmonyOS】服务卡片 API6 JSUI跳转不同页面并携带参数

【关键字】 服务卡片、卡片跳转不同页面、卡片跳转页面携带参数 【写在前面】 本篇文章主要介绍开发服务卡片时&#xff0c;如何实现卡片点击跳转不同页面&#xff0c;并携带动态参数到js页面。在此篇文章“服务卡片 API6 JSUI跳转不同页面”中说明了如果跳转不同页面&#xf…

十、W5100S/W5500+RP2040树莓派Pico<PING(ICMP)检测网络连通性>

文章目录 1 前言2 协议简介2.1 什么是PING2.2 PING的优点2.3 PING的原理2.4 应用场景 3 WIZnet以太网芯片4 PING网络设置示例概述以及使用4.1 流程图4.2 准备工作核心4.3 连接方式4.4 主要代码概述4.5 烧录验证 5 注意事项6 相关链接 1 前言 随着网络应用的日益丰富和普及&…

代码随想录打卡第五十六天|1143.最长公共子序列 ● 1035.不相交的线 ● 53. 最大子序和

1143.最长公共子序列 题目&#xff1a; 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变字符的相对顺序的…

iPhone听筒声音小怎么办?分享5种修复方法!

最近有小伙伴反映&#xff1a;苹果手机使用了一段时间后&#xff0c;听筒声音突然变小了&#xff0c;这是什么情况&#xff1f;这确实是一个让人感到困扰的问题&#xff0c;特别是在进行重要通话的时候&#xff0c;如果听不到对方说话&#xff0c;那场面将会十分尴尬。那么&…

C语言--顺序查找、折半查找

顺序查找 实现逻辑 顺序查找&#xff08;sequential search&#xff09;就是按照数组的顺序一 一比较数组中的元素的值和所查找的值。如下图表所示&#xff0c;遍历数组进行比较。若找到&#xff0c;则break跳出循环。 a[0]a[1]a[2]a[3]a[4]912221334229?2212?2222? 实现…

出海数字化,国产CRM如何支撑?纷享销客这样思考

2023年&#xff0c;疫情阴霾逐渐消散&#xff0c;企业全球化扩张的齿轮重新加速。以科技企业、高端制造业为代表的优秀企业引领中国企业出海浪潮&#xff0c;外资企业在华的经营活跃度也在提升。 无论是”外资在华经营“还是”中资出海“&#xff0c;这些具备全球化理想的企业…

0代码0侵入的安卓骨架屏框架----二期优化

本文是对自定义骨架屏框架的优化说明。 针对目前对骨架屏的需求及为了实现骨架屏而付出的繁重劳动&#xff0c;而设计的一款0编码0业务侵入的骨架屏框架。感兴趣的可以先去看看这篇文章&#xff1a;一种简单的Android骨架屏实现方案----0侵入0成本 额&#xff0c;如果不看&am…

玻色量子成功研制光量子计算专用光纤恒温控制设备——“量晷”

​近日&#xff0c;北京玻色量子科技有限公司&#xff08;以下简称“玻色量子”&#xff09;成功研制出一款高精度量子计算专用光纤恒温控制设备——“量晷”&#xff0c;该设备能将光纤的温度变化稳定在千分之一摄氏度量级&#xff0c;即能够做到0.001C的温度稳定维持&#xf…

5道谷歌面试题:即使是天才也要怀疑自己能力了(附GPT4答案)

谷歌google&#xff0c;美国的跨国科技企业&#xff0c;致力于互联网搜索、云计算、广告技术等领域&#xff0c;开发并提供大量基于互联网的产品与服务。 这样一家实力雄厚前景无量的公司是众多求职者梦寐以求的地方&#xff0c;然而&#xff0c;谷歌的面试题却把很多优秀人才…

技术贴 | 一文掌握 Google Test 框架

一、简介 1. 引言 在开发过程中&#xff0c;如何保证代码的质量以及程序的正确性成为了我们亟需解决的问题&#xff0c;其中测试用例成为了不必可少的一部分。测试用例不仅可以帮助我们验证代码的正确性&#xff0c;还能帮助我们捕获潜在的错误&#xff0c;提高代码的可靠性和…

IO模块:钢铁安全绿色生产的智能化助手

钡铼I/O模块以其卓越的性能和可靠性&#xff0c;为钢铁行业的安全绿色生产提供了强有力的支持。这个模块拥有出色的实时监测功能&#xff0c;能够精确捕捉现场设备的工作状态&#xff0c;确保设备的正常运行。通过采用先进的预测性维护技术&#xff0c;钡铼I/O模块能够提前发现…

传统金融机构加入代币化浪潮,新一轮加密周期的重要组成部分?

新加坡金融管理局 (MAS) 成立了由日本金融厅 (FSA)、英国金融行为监管局 (FCA) 和瑞士金融市场监管局 (FINMA) 组成“守护者计划”政策制定者组&#xff08;Project Guardian&#xff09;&#xff0c;正在计划对固定收益、外汇和资产管理产品进行资产代币化试点&#xff0c;以推…

Python 的 Web 自动化测试的实践

Web 测试是软件测试中比较重要的一个分支&#xff0c;而要实现 Web 自动化测试则要求测试人员能熟练掌握自动化测试工具和编程语言。介绍免费开源的 Web 测试工具 Selenium&#xff0c;以及流行的编程语言 Python。根据自动化测试的原理&#xff0c;对网页元素的常用定位方式&a…

smartLink HW-DP新版提供更多扩展功能——用于PROFIBUS和HART系统中物联网集成

Softing工业自动化的smartLink HW-DP网关可独立于控制器访问PROFIBUS DP网络&#xff0c;且新发布的1.30固件版本还提供了更多数据连接和传输的扩展功能。 smartLink HW-DP可无缝集成到PROFIBUS网络中&#xff0c;而不会影响现有设备的运行。该网关还可为新的和现有的PROFIBUS …

非常爆火的流量卡推广上线了

流量卡推广可以通过“聚量推文”申请&#xff0c;一手渠道 现在非常火的推广项目就是流量卡推广了&#xff0c;佣金价格高 普遍的价格是几十上百块&#xff0c;你一天推广10个收入就接近4位数&#xff0c;还是比较可观的 聚量推客专注于app拉新&#xff0c;网推项目&#xff…

博客系统-项目测试

自动化博客项目 用户注册登录验证效验个人博客列表页博客数量不为 0 博客系统主页写博客 我的博客列表页效验 刚发布的博客的标题和时间查看 文章详情页删除文章效验第一篇博客 不是 "自动化测试" 注销退出到登录页面,用户名密码为空 用户注册 Order(1)Parameterized…

MyBatis-Plus使用——配置yml参数 常用的注解@Table,@TableId,@IdType,@TableField,CRUD的API接口

前言 MyBatis-Plus (opens new window)&#xff08;简称 MP&#xff09;是一个 MyBatis (opens new window) 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 本系列博客结合实际应用场景&#xff0c;阐述MyBatis-Plus实际…

Python开发技能实战-通过配置的代理服务器在具有外网连接的环境中在Pycharm中运行python代码

实现功能 打开科学上网工具&#xff0c;使得能够在浏览器科学上网&#xff0c;通过科学上网工具的配置文件&#xff0c;可以看出本地和远程代理的映射关系&#xff0c;此时&#xff0c;远程地址本地地址&#xff0c;远程端口本地端口。 1、在程序中配置请求网页代理请求。不需…

GTS GtsUnofficialApisUsageTestCases Failed

GTS 测试GtsUnofficialApisUsageTestCases失败如下&#xff1a; junit.framework.AssertionFailedError: There are 102 violation(s) com.google.android.gm / Landroid/window/BackEvent;->getProgress()F / BLOCKED / LINKING com.google.android.gm / Landroid/window/…

java参数中的-、--、-X、-XX、-D

详细描述请参考&#xff1a;https://docs.oracle.com/en/java/javase/19/docs/specs/man/java.html Java标准选项&#xff08;以-、或者–开头&#xff09; Java标准选项被所有的Java虚拟机&#xff08;JVM&#xff09;实现所支持。 这些选项用于普通的动作&#xff0c;例如检…