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

算法设计策略-回溯法

子集和数

问题描述

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

回溯法求解

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

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

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

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

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

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

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

Bk(x0,x1,⋯,xk)=true,当且仅当∑i=0k−1wixi+∑i=kn−1wi≥M
  • 因为如果上式得不到满足,那么意味着当剩余的正数全部加入子集后,子集中的正数之和仍小于M,自然表明部分向量(x0,x1,⋯,xk)不可能导致一个答案状态。

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

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

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

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

∑i=0k−1wixi+∑i=kn−1wi≥M且∑i=0k−1wixi+wk≤M

子集和数算法

函数定义:

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

  • 前置条件:wi≤wi+1(0≤i<n−1),s+r≥m&&s+wk≤m(s=∑k−1i=0wixi,r=∑n−1i=kwi)
  • 后置条件:在以(x0,x1,⋯,xk)为根的子树上搜索答案状态

函数SumOfSub的初始条件是s=0,r=∑n−1i=0wi≥m和w0≤m。

//子集和数的回溯算法
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,⋯,xn−1)表示图G的m-着色判定问题的解。每个xi∈{1,2,3,⋯,m},0≤i<n,表示结点的颜色,这是显式约束。xi=0表示没有可用的颜色。因此解空间的大小为mn。其隐式约束可描述为:如果边(i,j)∈E,则xi≠xj。

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

图着色算法

//图的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-着色方案。搜索中使用约束函数剪去不可能包含答案结点的分枝。

时间分析

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

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

哈密顿环

问题描述

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

哈密顿环算法

对于n个结点的图G=(V,E)的哈密顿环问题,可采用n-元组表示问题的解(x0,x1,⋯,xn−1)。每个xi∈{0,1,⋯,n−1},0≤i<n,代表路径上一个结点的编号,这就是显式约束。因此解空间的大小为nn。其隐式约束可描述为:xi≠xj(0≤i,j<n,i≠j),且(xi,xi+1)∈E,xi,xi+1∈V(i=0,1,⋯,n−2),又(xn−1,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

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

  1. 算法设计与分析复习--回溯法

    算法设计与分析期末复习 主要参考: ​ 算法设计与分析(北京航空航天大学MOOC) ​ 算法设计与分析(北京大学MOOC) ​ 华中科技大学 计算机科学与技术学院 算法设计与分析 课堂教学PPT 五. ...

  2. 深大算法设计与分析实验二——分治法求最近点对问题

    源代码: 深大算法设计与分析实验二--分治法求最近点对问题代码-C/C++文档类资源-CSDN下载 目录 实验问题 一.实验目的: 二.内容: 三.算法思想提示 产生不重复的随机点算法: 蛮力算法: ...

  3. 哈工大威海算法设计与分析_计算机算法设计与分析第一章 算法概述

    晓强Deep Learning的读书分享会,先从这里开始,从大学开始.大家好,我是晓强,计算机科学与技术专业研究生在读.我会不定时的更新我的文章,内容可能包括深度学习入门知识,具体包括CV,NLP方向 ...

  4. 算法设计与分析:贪心算法 - 排课问题(DP与贪心的区别与应用)

    文章目录 前言 贪心算法概念 排课问题 问题描述与分析 动态规划求解 简化问题应用贪心算法 总结 本文参考UCAS卜东波老师算法设计与分析课程撰写 前言 前面两大章节的内容分治思想与动态规划暂时告一段 ...

  5. Apriori算法、FP-Growth算法、顺序分析、PrefixSpan算法

    Apriori算法.FP-Growth算法.顺序分析.PrefixSpan算法 目录 Apriori算法.FP-Growth算法.顺序分析.PrefixSpan算法 Apriori算法 FP-Grow ...

  6. 【机器学习】Apriori 算法进行关联分析和FP-growth算法

    [机器学习]Apriori 算法进行关联分析和FP-growth算法 文章目录 1 关联分析 2 FP-growth算法理解和实现 3 FP增长算法的频繁项集产生 4 FP-Growth关联分析算法在 ...

  7. 《数据结构、算法与应用 —— C++语言描述》学习笔记 — 回溯法

    <数据结构.算法与应用 -- C++语言描述>学习笔记 - 回溯法 一.算法思想 二.货箱装载 1.问题描述 2.回溯算法 3.实现 4.测试代码 一.算法思想 回溯法是搜索问题解的一种系 ...

  8. 算法设计与分析复习笔记(上)

    简介:本文是博主在复习算法设计与分析的笔记,参考了北大算法设计与分析以及王晓东编著的<计算机算法设计与分析>第四版相关内容,如有错误,欢迎指正. 文章目录 设计技术 分治 动态规划 设计技 ...

  9. 算法设计与分析 实验二 贪心算法

    实验2.<贪心算法实验> 一.实验目的 了解贪心算法思想 掌握贪心法典型问题,如背包问题.作业调度问题等. 二.实验内容 编写一个简单的程序,实现单源最短路径问题. 编写一段程序,实现找零 ...

最新文章

  1. 11个有用的移动网页开发App和HTML5框架
  2. 解决了无法显示验证码的问题
  3. Java-小技巧-004-jdk时间,jdk8时间,joda,calendar,获取当前时间前一周、前一月、前一年的时间...
  4. 关于寻路算法的一些思考(4):A* 算法的变体
  5. 时区日期处理及定时 (NSDate,NSCalendar,NSTimer,NSTimeZone) -- IOS(实例)
  6. Python内置函数(56)——set
  7. 金色传说:SAP-BC-下载数据及导入,导出EXCEL文件的控制问题
  8. 机器学习:Kmeans聚类算法总结及GPU配置加速demo
  9. win10重置计算机网络设置,win10网络重置后,win10网络重置怎么恢复
  10. 中证500-小盘股预警2015.4.2
  11. latch mysql_MySQL中的latch(閂鎖)詳解——易產生的問題以及原因分析
  12. vivo X70系列搭载自研V1芯片9月9日发布
  13. 2016年中国未来的新兴行业推荐
  14. WPF 使用 Direct2D1 画图入门
  15. (已更新)Discuz手机模板:NVBING5-APP手机版,界面美观大方,可封装安卓/苹果APP,模板文件+插件+分类信息导入文件
  16. 小白看了直呼细节--CPP“引用”
  17. 越吃越年轻的26种抗衰老食物
  18. opc服务器的数据文件,opc服务器与数据库间数据交换工具
  19. 学习笔记——Day1——Python歌词解析
  20. excel相同内容单元格数值等于固定值怎么做?

热门文章

  1. 面向对象编程思想-观察者模式
  2. 《Android开发艺术探索》读书笔记 (10) 第10章 Android的消息机制
  3. C++ STL学习笔记 : 2. unordered map 容器
  4. 经典问题之「分支预测」
  5. samba登陆密码不正确
  6. P1401 城市(30分,正解网络流)
  7. Mac下配置iterm2 支持rz sz命令
  8. 程序员容易不能生育?
  9. Mybatis各种模糊查询及#和$区别
  10. C#面向对象基础(六) 继承