0x08算法设计与分析复习(二):算法设计策略-回溯法2

参考书籍:算法设计与分析——C++语言描述(第二版)

算法设计策略-回溯法

子集和数

问题描述

已知n个不同的正数wi(0in1)的集合,求该集合的所有满足条件的子集,使得每个子集中的正数之和等于另一个给定的正数M

回溯法求解

对于子集和数问题问题,可采用两种不的解结构形式:可变长度元组和固定长度元组。

  • 采用可变长度元组表示解

    当采用可变长度元组表示解时,代表一个可行解的元组长度可以不同,成为一个k-元组(x0,x1,,xk1),0kn。元组的每个分量的取值可以是元素值,也可以是选入子集的正数的下标。通常的做法是列出入选子集的元素下标,如果采用这种形式的解,其显式约束可描述为:xi{j|j0j<n}xi<xi+1(0i<n1)。加入条件xi<xi+1可以避免产生重复子集现象。隐式约束如下:k1i=0wxi=M

  • 采用固定长度元组表示解

    固定长度n-元组(x0,x1,,xn1),xi{0,1},0i<nxi=0表示wi未选入子集;xi=1表示wi入选子集。采用这种形式的解,其显示约束可描述为:xi{0,1}(0i<n1)。问题的隐式约束是选入子集的正数之和等于M,即n1i=0wixi=M

一般称从n个元素的集合中找出满足某些性质的子集的状态空间树为子集树。子集树有2n个解状态,遍历子集树的时间为Ω(2n)

最后讨论子集和数的约束函数Bk。假定采用固定长度元组的结结构,已经知道,若约束函数Bk(x0,x1,,xk)=true,则算法需要进入考察(x0,x1,,xk)子树的过程,在本问题中,可以容易想到如下的约束函数:

Bk(x0,x1,,xk)=true,i=0k1wixi+i=kn1wiM

  • 因为如果上式得不到满足,那么意味着当剩余的正数全部加入子集后,子集中的正数之和仍小于M,自然表明部分向量(x0,x1,,xk)不可能导致一个答案状态。

如果假定n个正数wi,0in1已经按非减次序排列,那么还可以在上式约束条件中添加约束条件:

i=0k1wixi+wkM

  • 因为如果子集中加入下一个待选的正数wk(它是剩余正数中最小的),使整个子集之和已大于M,这显然意味着从剩余正数中选取任意一个正数加入到现有子集后都不可能使子集和数等于M

根据上面两式,可以得到约束函数:

Bk(x0,x1,,xk)为true,当且仅当:

i=0k1wixi+i=kn1wiMi=0k1wixi+wkM

子集和数算法

函数定义:

void SumOfSub(float s, int k, float r, int *x, float m, float *w)

  • 前置条件:wiwi+1(0i<n1),s+rm&&s+wkm(s=k1i=0wixi,r=n1i=kwi)
  • 后置条件:在以(x0,x1,,xk)为根的子树上搜索答案状态

函数SumOfSub的初始条件是s=0,r=n1i=0wimw0m

//子集和数的回溯算法
void SumOfSub(float s, int k, float r, int *x, float m, float *w)
{x[k]=1;if(s+w[k]==m){for(int j = 0;j<k;j++){//得到一个可行解cout << x[j]<<" ";}cout << endl;} else if(s+w[k]+w[k+1]<=m){//搜索左子树SumOfSub(s+w[k],k+1,r-w[k],x,m,w);}if((s+r-w[k]>=m)&&(s+w[k+1]<=m)){x[k]=0;//搜索右子树SumOfSub(s,k+1,r-w[k],x,m,w);}
}void SumOfSub(int *x,int x, float m,float *w)
{float r=0;for(int i = 0;i<n;i++){r=r+w[i];//计算r=\sum_{i=k}^{n-1}w[i];}if(r>=m && w[0]<=m)SumOfSub(0,0,r,x,m,w);
}

图的着色

问题描述

已知无向图G=(V,E)和m中不同颜色,如果只允许使用这m中颜色对图G的结点着色,每个结点着一种颜色,问是否存在一种着色方案,使得图中任意相邻的两个结点都有不同的颜色。这就是m-着色判定问题(m-colorability decision problem)。对给定的无向图G,求对图G的结点着色所需的最少颜色数m,使得图中任意两个相邻结点有不同的颜色。这被称为m-着色最优化问题(m-colorability optimization problem),整数m称为图G的着色数(chromatic number)

回溯法求解

设无向图G=(V,E)采用如下定义的邻接矩阵定义:

a[i][j]={10(i,j)E

下面采用n-元组(x0,x1,,xn1)表示图G的m-着色判定问题的解。每个xi{1,2,3,,m},0i<n,表示结点的颜色,这是显式约束xi=0表示没有可用的颜色。因此解空间的大小为mn。其隐式约束可描述为:如果边(i,j)E,则xixj

约束函数的设计:约束函数从隐式约束产生,对所有i和j(0i,j<k,ij),若a[i][j]=1,则xixj

图着色算法

//图的m-着色算法
template<class T>
void MGraph<T>::NextValue(int k,int m,int *x)
{//本函数在[1,m]中为x[k]确定一个值最小,且不与其邻接点冲突的颜色//x[k]=0表示没有可用颜色,颜色从1开始编号do{x[k]=(x[k]+1)%(m+1);//尝试下一种颜色if(!x[k])return;//没有可用颜色for(int j=0;j<k;j++){if(a[k][j] && x[k]==x[j]){//若(i,j)是图的边,且相邻结点k和j颜色相同break;//发生冲突,选择下一种颜色}}if(j==k)return;//成功选择一种颜色返回}while(1);
}template<class T>
void MGraph<T>::mColoring(int k,int m,int *x)
{do{NextValue(k,m,x);//为x[k]分配颜色if(!x[k])break;//x[k]=0表示没有适当的颜色if(k==n-1){//得到图G的一种m-着色方案for(int i=0;i<n;i++){cout << x[i] <<" ";}cout << endl;} else {//已经对前k个结点分配了颜色,尝试其余结点mColoring(k+1,m,x);}}while(1);
}template<class T>
void MGraph<T>::mColoring(int m,int *x)
{mColoring(0,m,x);
}

函数mColoring对一个给定的无向图G和m,列出图中结点的所有可能的m-着色方案。算法以深度优先方式生成状态空间树中的结点,寻找所有答案结点,即m-着色方案。搜索中使用约束函数剪去不可能包含答案结点的分枝。

时间分析

算法的计算时间上界可以由状态空间树的结点树n1i=0mi来确定。每个结点的处理时间即NextValue的执行时间为O(mn),因此总时间为:

i=1nmin=n(mn+1m)/(m1)=O(nmn)

哈密顿环

问题描述

已知图G=(V,E)是一个n个结点的连通图。连通图G的一个哈密顿环(Hamiltonian cycle)是图G的一个回路,它经过图中的每一个结点,且只经过一次。一个哈密顿环是从某个结点v0V开始,沿着图G的n条边环行的一条路径(v0,v1,,vn1,vn),其中,(vi,vi+1)E,(0i<n),它访问图中每个结点且只访问一次,最后返回开始结点,即除v0=vn外,路径上其余各点各不相同。并不是每个连通图都存在哈密顿环。

哈密顿环算法

对于n个结点的图G=(V,E)的哈密顿环问题,可采用n-元组表示问题的解(x0,x1,,xn1)。每个xi{0,1,,n1},0i<n,代表路径上一个结点的编号,这就是显式约束。因此解空间的大小为nn其隐式约束可描述为xixj(0i,j<n,ij),且(xi,xi+1)E,xi,xi+1V(i=0,1,,n2),又(xn1,x0)E

//哈密顿环算法
//,函数NextValue的功能是约束函数。
template<class T>
void MGraph<T>::NextValue(int k,int *x)
{//函数NextValue的功能是约束函数do{x[k]=(x[k]+1)%n;//下一个结点编号if(!x[k])return;if(a[x[k-1]][x[k]]){//检查(x[k-1],x[k])是否是图中一条边for(int j=0;j<k;j++){//检查与前k个结点是否相同if(x[j]==x[k])break;}if(j==k){//x[k]是当前可取的结点编号if((k<n-1)||((k==n-1)&&a[x[n-1]][x[0]]))return;}}}while(1);
}template<class T>
void ExtMGraph<T>::Hamiltonian(int k,int *x)
{//递归函数Hamiltonian实际计算哈密顿环do{NextValue(k,x);//产生x[k]的下一个值if(!x[k])return;//x[k]=0表示x[k]已经没有可取的值if(k==n-1){//输出一个哈密顿环for(int i=0;i<n;i++){cout << x[i]<<" ";}cout << "0" << endl;} else {//深度优先进入下一层Hamiltonian(k+1,x);}}while(1);
}template<class T>
void ExtMGraph<T>::Hamiltonian(int *x)
{Hamiltonian(1,x);//x[0]=0为约定的起始结点
}

转载于:https://www.cnblogs.com/born2run/p/9581367.html

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

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

相关文章

Android源码解析--SwipeMenuListView仿QQ聊天左滑

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请标明出处。 https://blog.csdn.net/lyhhj/article/details/50612714 绪论&#xff1a; 好久没写博客了&#xff0c;最近比较懒&#xff0c;不想写博客&#xff0c;但是在看书&#xff0c;看一些Android进阶的书&#…

UVA 125 Numbering Paths

题意 给出方向&#xff08;有向&#xff09;然后判断从一个点到另一个点的方案数。如果有无数条那么对应位置置为-1 直接先dp处理出来。dp[i][j] sum(dp[i][k]*dp[k][j]) 同时如果两点之间有无限条路径。那么这两点之间必然有一环存在。有f[k][k]!0 #include <map> #…

linux 循环执行ip停止服务,java调用远程服务器的shell脚本以及停止的方法实现

最近接了个需求&#xff0c;要求远程调shell脚本&#xff0c;你没听错&#xff01;&#xff01;&#xff01;需求就一句话&#xff0c;咱是谁&#xff0c;咱是优秀的开发选手。考虑再三&#xff0c;有两种实现方式&#xff1a;方案一&#xff1a;脚本所在服务器安装一个客户端&…

mysql-防止XSS攻击

1,防止Xss攻击 数据库查询数据操作,为了防止注入,要执行参数化查询,也就是直接利用execute直接进行sql语句的执行, 因为exexute本身就有接收语句变量的参数位, execute()函数本身就有接受SQL语句变量的参数位&#xff0c;只要正确的使用&#xff08;直白一点就是&#xff1a;使…

java main方法背后的故事?(转)

jvm java 看似一种语言&#xff0c;实则一个巨大的体系的王国&#xff0c;开发这么多年了&#xff0c;还是没有搞懂,我以为我懂了&#xff0c;可是过了一段时间又忘了&#xff0c;所以说还是没懂 1、main方法说起 编译完我们的java文件后&#xff0c;需要有个一含有main方法的类…

亲历腾讯WEB前端开发三轮面试经历及面试题

【一面】~110分钟 2014/09/24 11:20 星期三 进门静坐30分钟做题。 填空题大题问答题 >>填空题何时接触电脑 何时接触前端运算符 字符串处理 延时 display position XMLHttpRequest 正则Jquery绑定事件 cookie >>大题BOM浏览器…

Redis的数据结构之字符串

原文&#xff1a;http://blog.java1234.com/blog/articles/316.html 五种数据类型&#xff1a; 字符串&#xff08;String&#xff09; 字符串列表&#xff08;list&#xff09; 有序字符串集合&#xff08;sorted set&#xff09; 哈希&#xff08;hash&#xff09; 字符串集合…

linux搜索日志组合条件,find查找

find查找是生产中最常见的日志查找工具下面看看它的用法基本用法&#xff1a;find 查找路径 查找标准 查找到以后的处理动作查找路径&#xff1a;需要被查找的文件所在的路径&#xff0c;一定是个目录&#xff0c;默认情况下为当前的目录查找的标准&#xff1a;查找的…

常用的JPA标记 (转)

Table Table用来定义entity主表的name&#xff0c;catalog&#xff0c;schema等属性。 元数据属性说明&#xff1a; name: 表名catalog: 对应关系数据库中的catalogschema&#xff1a;对应关系数据库中的schemaUniqueConstraints:定义一个UniqueConstraint数组&#xff0c;指定…

JavaBean技术的一些讲解

JavaBean: 由于原先的jsp的html代码和css代码以及java代码都是写在一起的&#xff0c;所以看起来就比较冗余&#xff0c;同时 也体现不了javaBean中面向对象的思想的{当然可以同过jstl标签库以及mvc框架来脱离java代码&#xff0c;但是这也是必不可少的} 在这里对于Javabean的一…

linux网卡名称乱编,小斗CentOS7.x网卡名称错乱、及网卡启动失败。

本帖最后由 Zack 于 2018-5-31 13:39 编辑最近在搞CentOS7装机的事情&#xff0c;在此记录期间遇到关于网卡方面的坑&#xff0c;整理分享下&#xff0c;以免大家继续再踩。一、在CentOS7默认装完系统之后网卡名称一改之前的名称习惯&#xff0c;网卡名称为enoxxxxx(之前命名规…

block传值 链接

iOS传值之block传值(一)转载于:https://www.cnblogs.com/dqxu/p/4016117.html

Maven——继承和聚合

实际项目中&#xff0c;可能正要构建一个大型的系统&#xff0c;但又不想一遍又一遍的重复同样的依赖元素&#xff0c;这种情况是经常出现的。不过还好&#xff0c;maven提供了继承机制&#xff0c;项目可以通过parent元素使用继承&#xff0c;可以避免这种重复。当一个项目声明…

隐藏linux操作系统版本信息,linux centos 如何查看操作系统版本信息?

本文介绍常用的四种查看linux下查看系统版本信息的方法&#xff1a;一、uname -a[appVM_11_211_centos ~]$ uname -aLinux VM_11_211_centos 2.6.32-504.30.3.el6.x86_64 #1 SMP Wed Jul 15 10:13:09 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux二、cat /proc/version[appVM_11_2…

iframe css练习

转载于:https://www.cnblogs.com/wenhuan/p/4019154.html

关于缓存的几篇好文章

追求极致&#xff1a;从技术细节看美团架构 Memcache架构新思考 Memcache应用场景介绍&#xff0c;说明[zz] 大型web系统数据缓存设计-l转载 大型网站后台架构的Web Server与缓存 Intelligence Computing 微博到底有多重视分布式缓存&#xff08;上&#xff09; Beanstalkd 一个…

linux 复制分区文件,dd复制分区后目标分区的大小变成原分区了

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼我使用了dd if/dev/sda1 of/dev/sdb1这个命令,想复制分区sda1上的所有数据但是我原本sdb1是150G,dd之后,挂载后变成55G了(df -h输出结果)(也就是sda1的大小 )但是我用fdisk -l 得到的信息还是150G请问这种情况如何解决??acePerso…

Elasticsearch 5.2.x 使用 Head 插件连接不上集群

0、前言 时光荏苒&#xff0c;ES转眼间就从2.X跳到了5.X。。。忆往昔峥嵘岁月&#xff0c;奈何ES社区太活跃&#xff0c;版本跳的比房价还快啊。。。话说回来&#xff0c;需要部署一套Elasticsearch 5.2.1 即本月最新推出的ES新力作&#xff0c;发现很多用法已经不一样了。。。…

Javascript---Immediately-Invoked Function Expression (IIFE)立即执行的函数表达式

1.一下是几种形式的函数调用&#xff1a; 各种调用的效率&#xff1a;在这编文章中有谈到&#xff1a; http://suqing.iteye.com/blog/1981591 // Either of the following two patterns can be used to immediately invoke // a function expression, utilizing the functions…

extern 使用方法具体解释

在C语言中&#xff0c;修饰符extern用在变量或者函数的声明前&#xff0c;用来说明“此变量/函数是在别处定义的。要在此处引用”。&#xff08;extern能够置于变量或者函数前&#xff0c;以标示变量或者函数的定义在别的文件里&#xff0c;提示编译器遇到此变量和函数时在其它…