实验四 回溯法(图着色问题)
回溯法实验(图的m着色问题)
算法分析与设计实验报告第六次附加实验cout<<endl;}elsefor(int i=1;i<=m;i++){x[t]=i;if(ok(t)) Backtrack(t+1);//回溯,继续寻找下一层x[t]=0;//回到最初状态,使x[1]继续尝试其他填色的可能解}}测试结果当输入图如下时:结果如下:12435只要输入边即可当输入的图如下时:结果如下:附录:完整代码(回溯法)//图的m着色问题回溯法求解#include<iostream>using namespace std;class Color{friend void mColoring(int,int,int **);private:bool ok(int k);void Backtrack(int t);int n, //图的顶点个数m, //可用颜色数**a, //图的邻接矩阵*x; //当前解long sum; //当前已找到的可m着色的方案数};bool Color::ok(int k) //检查颜色可用性{for(int j=1;j<=n;j++)if((a[k][j]==1)&&(x[j]==x[k])) //两个点之间有约束且颜色相同return false;return true;}void Color::Backtrack(int t){if(t>n) //到达叶子节点{sum++; //可行解+1cout<<"着色: ";for(int i=1;i<=n;i++) //输出可行解方案cout<<x[i]<<" ";cout<<endl;}elsefor(int i=1;i<=m;i++){x[t]=i;if(ok(t)) Backtrack(t+1);//回溯,继续寻找下一层x[t]=0;//回到最初状态,使x[1]继续尝试其他填色的可能解 }}void mColoring(int n,int m,int **a){Color X;//初始化XX.n=n;X.m=m;X.a=a;X.sum=0;int *p=new int[n+1];for(int i=0;i<=n;i++)p[i]=0;X.x=p;cout<<"顶点: ";for(int i=1;i<=n;i++) //用于输出结果cout<<i<<" " ;cout<<endl;X.Backtrack(1); //从顶点1开始回溯delete []p;cout<<"解法个数:"<<X.sum<<endl;}int main(){int n;int m;cout<<"please input number of node:";cin>>n;cout<<"please input number of color:";cin>>m;int **a=new int*[n+1];for(int i=0;i<=n;i++)a[i]=new int[n+1];for(int i=0;i<=n;i++) //利用抽象图实现图的邻接矩阵for(int j=0;j<=n;j++)a[i][j]=0;int edge;cout<<"please input adjacent edge number:";cin>>edge;int v,w;cout<<"please inout adjacent edge:"<<endl; //只要输入边即可for(int i=0;i<edge;i++){cin>>v>>w; //由于是无向图,所以对应的邻接矩阵对应的边都有,即v->m,m->v都有边a[v][w]=1;a[w][v]=1;}mColoring(n,m,a);system("pause");return 0;}。
图的着色问题--C++实现(含详细注释)
图的着色问题一、题目简述(1) 图的m-着色判定问题给定一个无向连通图 G 和 m 种不同的颜色。
用这些颜色为图 G 的各顶点着色,每个顶点着一种颜色,是否有一种着色法使 G 中任意相邻的两个顶点着不同颜色?(2) 图的m-着色优化问题若一个图最少需要 m 种颜色才能使图中任意相邻的两个顶点着不同颜色,则称这个数 m 为该图的色数。
求一个图的最小色数 m 的问题称为m-着色优化问题。
二、算法思想1. m-着色判定问题总体思想:通过回溯的方法,不断为每一个节点着色,每个点的颜色由一个数字代表,初始值为1。
在对前面 step - 1 个节点都合法的着色之后,开始对第 step 个节点进行着色。
如果 n 个点均合法,且颜色数没有达到 m 种,则代表存在一种着色法使 G中任意相邻的两个顶点着不同颜色。
具体步骤:1. 对每个点 step ,有 m 种着色可能性,初始颜色值为1。
2. 检查第 step 个节点颜色的可行性,若与某个已着色的点相连且颜色相同,则不选择这种着色方案,并让颜色值加1,继续检查该点下一种颜色的可行性。
3. 如果第 step 点颜色值小于等于 m ,且未到达最后一个点,则进行对第 step + 1 点的判断。
4. 如果第 step 点颜色值大于 m ,代表该点找不到合适的分配方法。
此时算法进行回溯,首先令第 step 节点的颜色值为0,并对第 step - 1 个点的颜色值+1后重新判断。
5. 如果找到一种颜色使得第 step 个节点能够着色,说明 m 种颜色的方案是可行的。
6. 重复步骤2至5,如果最终 step 为0则代表无解。
2. m-着色优化问题基于问题1,对于一个无向图 G ,从1开始枚举染色数,上限为顶点数,第一个满足条件的颜色数即为所求解。
三、实现过程(附代码)1. m-着色判定问题#include<iostream>using namespace std;int color[100]; // 每个点的颜色int mp[100][100]; // 图的邻接矩阵int n, m, x; // n顶点,m种颜色方案,x条边bool check(int step) {// 判断与step点相邻的点,颜色是否与step点相同,若相同则返回falsefor (int i=1; i<=n; i++) {if (mp[step][i] ==1&&color[i] ==color[step]) {return false;}}return true;}bool Solve(int m) {// 求解是否可以找到一种可行的染色方案int step=1; // step指示当前节点while (step>=1) {color[step] +=1; // 假定颜色值从1开始,若为回溯,选择下一种方案while (color[step] <=m) { // 按照问题条件选择第step点颜色if (check(step)) {break;} else {color[step]++; // 搜索下一个颜色}}if (color[step] <=m&&step==n) { // 如果找完n个点,且染色方法小于等于m种 return true;} else if (color[step] <=m&&step<n) {step++; // 求解下一个顶点} else { // 如果染色数大于m个,回溯color[step] =0; // 回溯,该点找不到合适的分配方法,对上一点进行分析step--;}}// 如果step退到0,则代表无解return false;}int main() {int i, j;bool ans=false;cout<<"输入顶点数n和着色数m"<<endl;cin>>n>>m;cout<<"输入边数"<<endl;cin>>x;cout<<"具体输入每条边"<<endl;for (int p=0; p<x; p++) { // 以无向邻接矩阵存储边cin>>i>>j;mp[i][j] =1;mp[j][i] =1;}if (Solve(m)) {cout<<"有解";} else {cout<<"无解";}return0;}2. m-着色优化问题#include<iostream>using namespace std;int color[100]; // 每个点的颜色int mp[100][100]; // 图的邻接矩阵int n, m, x; // n顶点,m种颜色方案,x条边bool check(int step) {// 判断与step点相邻的点,颜色是否与step点相同,若相同则返回falsefor (int i=1; i<=n; i++) {if (mp[step][i] ==1&&color[i] ==color[step]) {return false;}}return true;}bool Solve(int m) {// 求解是否可以找到一种可行的染色方案int step=1; // step指示当前节点while (step>=1) {color[step] +=1; // 假定颜色值从1开始,若为回溯,选择下一种方案while (color[step] <=m) { // 按照问题条件选择第step点颜色if (check(step)) {break;} else {color[step]++; // 搜索下一个颜色}}if (color[step] <=m&&step==n) { // 如果找完n个点,且染色方法小于等于m种 return true;} else if (color[step] <=m&&step<n) {step++; // 求解下一个顶点} else { // 如果染色数大于m个,回溯color[step] =0; // 回溯,该点找不到合适的分配方法,对上一点进行分析step--;}}// 如果step退到0,则代表无解return false;}int main() {int i, j;bool ans=false;cout<<"输入顶点数n"<<endl;cin>>n;cout<<"输入边数"<<endl;cin>>x;cout<<"具体输入每条边"<<endl;for (int p=0; p<x; p++) { // 以无向图邻接矩阵存储边 cin>>i>>j;mp[i][j] =1;mp[j][i] =1;}for (m=1; m<=n; m++) { // 从小到大枚举着色数mif (Solve(m)) { // 如果有解,输出答案并跳出循环cout<<"最小色数m为 "<<m;break;}}return0;}四、结果及分析问题1测试用例:问题2测试用例:经检验,最少着色数的范围为2-4,意味着使 G 中任意相邻的两个顶点着不同颜色最多需要4种颜色。
图的着色问题
问题来源
图的着色
通常所说的着色问题是指下述两类问题: 通常所说的着色问题是指下述两类问题: 1.给定无环图G=(V,E),用m种颜色为图中 的每条边着色,要求每条边着一种颜色, 的每条边着色,要求每条边着一种颜色,并 使相邻两条边有着不同的颜色, 使相邻两条边有着不同的颜色,这个问题称 为图的边着色问题。 为图的边着色问题。 2.给定无向图G=(V,E),用m种颜色为图中 的每个顶点着色,要求每个顶点着一种颜色, 的每个顶点着色,要求每个顶点着一种颜色, 并使相邻两顶点之间有着不同的颜色, 并使相邻两顶点之间有着不同的颜色,这个 问题称为图的顶着色问题。 问题称为图的顶着色问题。
化简得
( a + bd )(b + aceg )(c + bdef )( d + aceg )(e + bcdf )( f + ceg )( g + bdf )
求极小覆盖法- 求极小覆盖法-布尔代数法
Step3:从中挑选所用极大独立集个数最小者, Step3:从中挑选所用极大独立集个数最小者, 即为X 即为X(G) 但上述子集的颜色数都不是X ),正确的应 但上述子集的颜色数都不是X(G),正确的应 该是X =3,该子集为: {b,d,f}中的 该是X(G)=3,该子集为:给{b,d,f}中的 b,d,f涂颜色 涂颜色1 {a,e,g}中a,e,g涂颜色 涂颜色2 b,d,f涂颜色1,为{a,e,g}中a,e,g涂颜色2为 {a,c,g}中的 涂颜色3 中的c {a,c,g}中的c涂颜色3。 由此可见, 由此可见,求色数其需要求极大独立集以 及一切若干极大独立集的和含所有顶点的子 对于大图, 集,对于大图,因为图计算量过大而成为实 际上难以凑效的算法,所以不是一个好算法, 际上难以凑效的算法,所以不是一个好算法, 一般我们采用贪心法等近似算法来求解 。
第8节图论应用实例_图着色问题
第8节图论应用实例_图着色问题预备知识_回溯法回溯法:在实际生活中,有些问题是不能用数学公式去解决的,它需要通过一个过程,此过程要经过若干个步骤才能完成,每一个步骤又分为若干种可能;同时,为了完成任务,还必须遵守一些规则,但这些规则无法用数学公式表示,对于这样一类问题,一般采用搜索的方法来解决,回溯法就是搜索算法(广度优先、深度优先等)中的一种控制策略,它能够解决许多搜索中问题。
回溯法基本思想:试探法,撞了南墙就回头。
(一般采用深度优先搜索策略) 搜索策略:深度优先(不撞南墙不回头)。
在搜索过程中,如果求解失败,则返回搜索步骤中的上一点,去寻找新的路径,以求得答案。
要返回搜索,前进中的某些状态必须保存,才能使得退回到某种状态后能继续向前。
白话搜索:如果用数组存放搜索信息,i表示数组下标(当前状态), ++i表示往前走(下一个状态),--i表示回溯(往回退,返回上一次状态)。
第8节图论应用实例_图着色(graph coloring)问题数学定义:给定一个无向图G=(V, E),其中V为顶点集合,E为边集合,图着色问题即为将V分为k个颜色组(k为颜色数),每个组形成一个独立集,即其中没有相邻的顶点。
其优化版本是希望获得最小的k值。
典型应用:地图的着色、调度问题等。
k-着色判定问题:给定无向连通图G和k种不同的颜色。
用这些颜色为图G的各顶点着色,每个顶点着一种颜色,是否有一种着色法使G中任意相邻的2个顶点着不同颜色,例四色问题。
设有如图1的地图,每个区域代表一个省,区域中的数字表示省的编号,现在要求给每个省涂上红、蓝、黄、白四种颜色之一,同时使相邻的省份以不同的颜色区分。
课外拓展:搜索“四色问题”,了解四色问题相关知识。
5674231图1问题分析:(1)属于图的搜索问题。
将问题简化:将每个省抽象为一个点,省之间的联系看为一条边,可以得到图2。
16751432图2(2)用邻接矩阵表示各省之间的相邻关系,二维数组实现:1 表示省i与省j相邻, ,,ri,j,,0 表示省i与省j不相邻,由图2可以得到如下矩阵:(对称矩阵)1 2 3 4 5 6 71 0 1 0 0 0 0 12 1 0 1 1 1 1 13 0 1 0 1 0 0 04 0 1 1 0 1 0 05 0 1 0 1 0 1 06 0 1 0 0 1 0 17 1 1 0 0 0 1 0 为一对称矩阵。
《算法设计与分析》课程实验报告 (回溯法(二))
《算法设计与分析》课程实验报告实验序号:10实验项目名称:实验十一回溯法(二)一、实验题目1.图的着色问题问题描述:给定无向连通图G和m种不同的颜色。
用这些颜色为图G的各顶点着色,每个顶点着一种颜色。
如果有一种着色法使G中每条边的2个顶点着不同颜色,则称这个图是m可着色的。
图的m着色问题是对于给定图G和m种颜色,找出所有不同的着色法。
2.旅行商问题问题描述:给出一个n个顶点的带权无向图,请寻找一条从顶点1出发,遍历其余顶点一次且仅一次、最后回到顶点1的最小成本的回路——即最短Hamilton回路。
3.拔河比赛问题描述:某公司的野餐会上将举行一次拔河比赛。
他们想把参与者们尽可能分为实力相当的两支队伍。
每个人都必须在其中一只队伍里,两队的人数差距不能超过一人,且两队的队员总体重应该尽量接近。
4.批处理作业调度问题描述:给定n个作业的集合J=(J1,J2, .. Jn)。
每个作业J都有两项任务分别在两台机器上完成。
每个作业必须先由机器1处理,再由机器2处理。
作业i需要机器j的处理时间为tji(i=1,2, ..n; j=1,2)。
对于一个确定的作业调度,设Fji是作业i在机器j上完成处理的时间,则所有作业在机器2上完成处理的时间和,称为该作业调度的完成时间和。
批处理作业调度问题要求,对于给定的n个作业,制定最佳作业调度方案,使其完成时间和达到最小。
二、实验目的(1)通过练习,理解回溯法求解问题的解状态空间树与程序表达的对应关系,熟练掌握排列树、子集树的代码实现。
(2)通过练习,体会减少搜索解空间中节点的方法,体会解的状态空间树的组织及上界函数的选取对搜索的影响。
(3)通过练习,深入理解具体问题中提高回溯算法效率的方法。
(4)(选做题):在掌握回溯法的基本框架后,重点体会具体问题中解的状态空间搜索时的剪枝问题。
三、实验要求(1)每题都必须实现算法、设计测试数据、记录实验结果,并给出时间复杂度分析。
四、实验过程(算法设计思想、源码)1.图的着色问题(1)算法设计思想用邻接矩阵a[i][j]存储无向图,对于每一个顶点有m种颜色可以涂。
图着色问题——精选推荐
图着⾊问题⼀、图着⾊问题(1)图的m可着⾊判定问题给定⽆向连通图G和m种不同的颜⾊。
⽤这些颜⾊为图G的各顶点着⾊,每个顶点着⼀种颜⾊。
是否有⼀种着⾊法使G中每条边的2个顶点着不同颜⾊。
(2)图的m可着⾊优化问题若⼀个图最少需要m种颜⾊才能使图中每条边连接的2个顶点着不同颜⾊,则称这个数m为该图的⾊数。
⼆、m可着⾊判定问题的解法【算法】(1)通过回溯的⽅法,不断的为每⼀个节点着⾊,在前⾯cur-1个节点都合法的着⾊之后,开始对第cur-1个节点进⾏着⾊,(2)这时候枚举可⽤的m个颜⾊,通过和第cur-1个节点相邻的节点的颜⾊,来判断这个颜⾊是否合法(3)如果找到那么⼀种颜⾊使得第cur-1个节点能够着⾊,那么说明m种颜⾊的⽅案在当前是可⾏的。
(4)cur每次迭代加1,如果cur增加到N并通过了检测,说明m种颜⾊是可满⾜的。
(5)注意,这⾥只是要求判断m种颜⾊是否可满⾜,所以找到任何⼀种⽅案就可以了。
【代码实现】#include<iostream>#include<cstring>using namespace std;const int maxn = 105;int G[maxn][maxn];int color[maxn];bool ans;int n,m,k;void init(){ans = 0;memset(G, 0 , sizeof G);memset(color, 0 , sizeof color);}void dfs(int cur){if(cur > n) {ans = 1;return;}for(int i=1; i<=m; i++){ //对cur结点尝试使⽤每⼀种颜⾊进⾏涂⾊bool flag = 1;//cur之前的结点必被涂⾊for(int j=1; j<cur; j++){if(G[j][cur] == 1 && color[j] == i){flag = 0;//只要有⼀个冲突都不⾏break;}}//如果可以涂上i颜⾊,则考虑下⼀个结点的情况if(flag){color[cur] = i;dfs(cur + 1);}//如果到这⼀步第cur个结点⽆法着⾊,则返回探寻其他⽅案else color[cur] = 0;//回溯 ;}}int main(){while(cin>>n>>k>>m){init();for(int i=1; i<=k; i++){int x,y;cin>>x>>y;G[x][y] = G[y][x] = 1;}dfs(1);cout<<ans<<endl;}return0;}三、m可着⾊拓展【问题】在上述基础上,求出m种颜⾊能够给图G涂⾊的总总⽅案数量【算法】由于这个时候要求总⽅案数量,所以在找到⼀种可⾏⽅案后,总是进⾏回溯再搜索其他的解决⽅案,与上⾯不同,上⾯是只需要找出⼀种⽅案即可,所以如果找到了就不需要再回溯了,所以在这⾥只需要把回溯语句的位置写到dfs语句的后⾯即可。
回溯算法补充内容(N皇后、图的着色问题)
• 子集合数问题的递归回溯算法
• • Procedure Sumofsum(s,k,r) //找w(1:n)中和数为M的所有子集。进入此过程的时候x(1),…,x(k-1)的值已经确定。 s=w(1)x(1)+…+w(k-1)x(k-1); r=w(k)+…+w(n) 这些W(j)按非降次的顺序排列。假定 w(1)<=M, w(1)+…+w(n)>=M
N皇后问题的所有解
end while
end
PLACE (k)的程序
• Procedure PLACE(k) // 如果一个皇后能放在第k行和x(k)列,返回ture;否则返回false。x是一个全局 变量,进入此过程的时候已经置了k个值。ABS(r)过程返回r的绝对值 global x(1:k); integer i,k; i=1; while i<k do if x(i)==x(k) or ABS(x(i)-x(k))==ABS(i-k) //在同一列 或者在同一斜角线上 有两个皇后 then return (false) end if i=i+1; end while return (true) end
Global integer m,n X(1:n) Boolean Graph(1:n,1:n) integer k loop X(k)=(X(k)+1)mod(m+1) //试验下一个最高标值的颜色 if X(k)==0 return //全部颜色用完 endif for j=1:n if Graph(k,j)and X(k)==X(j) //如果(k,j)是一条边并且临近的结点有相同的颜色 exit endif endfor if j==n+1 // 找到了一种新颜色 return endif endloop end
回溯法解决图着色问题
回溯法解决图着色问题回溯法解决图着色问题2010-05-20 20:151回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。
回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。
用回溯算法解决问题的一般步骤为:一、定义一个解空间,它包含问题的解。
二、利用适于搜索的方法组织解空间。
三、利用深度优先法搜索解空间。
四、利用限界函数避免移动到不可能产生解的子空间。
问题的解空间通常是在搜索问题的解的过程中动态产生的,这是回溯算法的一个重要特性。
回溯法是一个既带有系统性又带有跳跃性的的搜索算法。
它在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。
算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。
如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。
否则,进入该子树,继续按深度优先的策略进行搜索。
回溯法在用来求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。
而回溯法在用来求问题的任一解时,只要搜索到问题的一个解就可以结束。
这种以深度优先的方式系统地搜索问题的解的算法称为回溯法,它适用于解一些组合数较大的问题.递归回溯:由于回溯法是对解空间的深度优先搜索,因此在一般情况下可用递归函数来实现回溯法如下:procedure try(i:integer);var begin if in then输出结果else for j:=下界to上界do begin x:=h[j];if可行{满足限界函数和约束条件}then begin置值;try(i+1);end;end;end;说明:i是递归深度;n是深度控制,即解空间树的的高度;可行性判断有两方面的内容:不满约束条件则剪去相应子树;若限界函数越界,也剪去相应子树;两者均满足则进入下一层;搜索:全面访问所有可能的情况,分为两种:不考虑给定问题的特有性质,按事先顶好的顺序,依次运用规则,即盲目搜索的方法;另一种则考虑问题给定的特有性质,选用合适的规则,提高搜索的效率,即启发式的搜索。
算法设计与分析课件--回溯法-图的m着色问题
4
5
C
C
n=5, m=3的GCP: 解形式(x1,x2, x3, x4, x5) xi =1(红色), 2(绿色), 3(蓝色)
X3=3
D
9
5.6 图的m着色问题
GCP示例
1
A
AA
A
A X1=1
2
3
X1=1
X1=1 X1=1
B
B
B
B X2=2
4
5
X2=2
C
X2=2
C
C X3=3
n=5, m=3的GCP: 解形式(x1,x2, x3, x4, x5) xi =1(红色), 2(绿色), 3(蓝色)
7
5.6 图的m着色问题
GCP示例
1
AA
A
2
3
X1=1
X1=1
B
B
X2=2
4
5
C
n=5, m=3的GCP: 解形式(x1,x2, x3, x4, x5) xi =1(红色), 2(绿色), 3(蓝色)
8
5.6 图的m着色问题
GCP示例
1
AA
A
A
2
3
X1=1
X1=1 X1=1
B
B
B
X2=2 X2=2
A
X1=1
2
3
B
X2=2 X2=3
4
5
C
X3=3
G
X3=2
n=5, m=3的GCP: 解形式(x1,x2, x3, x4, x5) xi =1(红色), 2(绿色), 3(蓝色)
D
X4=1
E
X5=3
F
H
X4=1
回溯法方法简介
回溯法方法简介回溯法(backtracking)是一种常用于解决组合优化问题和搜索问题的算法。
它通过逐步建立解决方案的过程,并在某一步发现不满足条件时回溯到前一步,尝试其他可能的选择,直至找到满足条件的解决方案或者确定无解。
回溯法的思想类似于穷举搜索,但通过一些剪枝等优化策略,可以提高搜索效率。
回溯法是许多经典算法问题的核心思想,如八皇后问题、0-1背包问题、图的着色问题等。
回溯法的过程通常包括五个步骤:1. 选择解空间;2. 约束条件;3. 判断当前解是否满足约束条件;4. 如果满足条件则记录当前解,否则回溯到前一步;5. 继续遍历其他分支,直至找到最终解或确定无解。
回溯法通常使用递归的方式来实现,其中递归函数包括参数表示当前搜索深度、当前解决方案、约束条件等信息。
在递归函数中,根据约束条件和当前解决方案,判断是否需要继续搜索或者回溯。
通过不断调用递归函数,可以逐步构建解空间,并寻找满足条件的解决方案。
回溯法的优点在于可以找到问题的所有解(或满足条件的解),适用于许多组合优化问题和搜索问题。
回溯法的搜索过程中可以使用剪枝等策略来提高效率,避免不必要的搜索。
回溯法的缺点在于可能需要遍历整个解空间,并且在某些情况下可能会导致比较大的时间复杂度。
回溯法在实际应用中有许多经典问题的解决方案。
八皇后问题是回溯法的典型案例。
八皇后问题是一个经典的棋盘游戏问题,要求在8×8的国际象棋棋盘上放置8个皇后,使得彼此之间不能相互攻击。
通过回溯法逐步尝试不同的布局,可以找到所有满足条件的解决方案。
同样,回溯法在解决0-1背包问题、图的着色问题、旅行推销员问题等组合优化问题中也有广泛的应用。
除了组合优化问题,回溯法也常用于搜索问题的解决。
在图的遍历中,可以使用回溯法来寻找从起点到终点的路径。
在人工智能领域,回溯法也常用于解决逻辑推理、规划等问题。
通过对搜索空间进行回溯和剪枝,可以高效地找到问题的解决方案。
回溯法是一种重要的算法思想,适用于解决组合优化问题和搜索问题。
回溯法解四色方柱问题实验报告 JAVA源代码
算法与分析课程设计报告题目:回溯法解四色方柱问题专业:网络工程班级:1020552学号:102055203姓名:郑贺太原工业学院计算机工程系2012年11月17日一、算法问题描述设有4个立方体,每个立方体得每一面用红、黄、蓝、绿4种颜色之一染色。
要把这4个立方体叠成一个方形柱体,使得柱体使得4个侧面的每一侧均有4种不同的颜色。
同时,4个顶面和4个底面也有4种不同的颜色。
试设计一个回溯算法,计算出4个立方体的一种满足要求的叠置方案。
二、算法问题形式化表示这个问题关键就是用一种方法求出当一个立方体按照一个特定朝向摆好之后,其它各个面对应于所要摆的柱体的哪个面的问题,知道这种对应关系以后,就可以得到各个面的颜色了,然后进行回溯算法。
注意:需要两个约束才能确定一个立方体的朝向。
1、首先要确保任意两个顶面和底面都不能有相同的颜色。
2、在立方体进行旋转,知道四个侧面的颜色都不相同是确定为一个方案。
事实上,这个四色方柱问题,如果用逆推想会好理解一些,现在设将这四个立方体组合成了一个方形柱体,我们可以先选择一个立方体的符合条件的顶面和底面,之后我们可以将它的侧面展开这样会形成一个4*4的矩阵,该4*4矩阵上每行的四个值相当于原小立方体的四个侧面的着色(左、右、前、后对应于1、2、3、4)列上的四个值就是表示四个小立方体合成方形柱体后柱体上某个侧面的着色了,这样就可以利用类似于N皇后的回溯算法的思路了,N皇后的要求是不能相互攻击而这个题根据要求就是使每列上的着色值都不同。
用4元数组X[i,j],(i=1、2、3、4,j=1、2、3、4)表示第i 个立方体第j 个面所图颜色,由于不允许将两个颜色放在同一列,所以解向量中的X[i]互不相同。
将n*n 格棋盘看作二维矩阵,其行号从上到下以此表示四个立方体,列号从左到右依次表示左、右、前、后立方体的六个面。
从棋盘自上来下同一竖直线上,因此,两个颜色放置的位置分别是),(j i 和),(l k ,且k i =!、l j =&&l]X[k,j]!X[i,=,此条件下确保四方柱的每个侧面都有四种不同的颜色。
图着色问题的回溯算法
图着色问题的回溯算法●图着色问题的回溯算法:(非递归算法,求一个解)非递归算法:算法m-COLORING输入:正整数m, n和含n个顶点的无向连通图G的邻接矩阵graph。
输出: 图G的m着色问题的一个解x[1..n],若无解,则输出no。
solution。
flag=false //用flag标记问题是否有解。
k=1 ; x[1]=0while k>=1 and not flagwhile x[k]<="" not="" p="">x[k]=x[k]+1 //试将第k个顶点着下一种颜色。
if color(k) then //第k个顶点的当前颜色合法。
if k=n then flag=true //x[1..n]是一个解else //x[1..k]是部分解k=k+1 //准备对下一个顶点着色。
x[k]=0end ifend if //否则,剪枝end whilek=k-1//回溯end whileif flag then output x //输出一个解else output “no solution”//输出无解end m-COLORING过程color (k)//在前k-1个顶点已着色的情况下,判断第k个顶点是否可//着颜色x[k], 是则返回true, 否则返回false。
j=1while j<k< p="">if graph[k, j]*x[k]=x[j] thenreturn falseelse j=j+1end whilereturn trueend color递归算法:算法m-COLORING输入:正整数m, n和含n个顶点的无向连通图G的邻接矩阵graph。
输出: 图G的m着色问题的一个解x[1..n],若无解,则输出no。
flag=coloring( 1 )if flag then output x //输出一个解else output “No solution”//输出无解end NQUEENREC1过程coloring(k)//在前k-1个顶点已着色且满足着色条件的情况下,求图的// m着色问题的一个解,有解则返回true, 否则返回false。
算法设计与分析 回溯算法2
解空间树第j层的成员由 的值进行分割
24
解空间
子集树: n=4
1
1
0
0
1
0
25
0-1背包问题
约束函数
用cw(i)到达第i层时扩展节点的重量,即
=
=
那么,约束函数为:
= − +
剪枝
如果C(i)>W,那么停止搜索第i层及该节点以下的层搜索,否则继续搜索。
—许多着色问题可以用回溯法来解决
2
着色问题
●四色定理
表述任何一个平面地图可以用不超过四种颜色进行着色,使得
拥有同一边界线的国家有着不同的颜色。
●对大多数地图,要找到合法的着色方案很容易
●对某些地图,要找到合法的着色方案却是很困难的
●更一般的问题
你可以把地图着色问题转化为m-着色问题
3
四色原理
●世界近代三大数学难题之一(另外两个是费马定理和哥德巴赫猜想)。
解空间
假设解可以有向量( , ,…, )表示, ∈{0,1}, =1表示物品i被放进
背包, =0表示物品i不被放进背包。
23
0-1背包问题
σ
●0-1背包问题可以被形式地描述为如下形式: =
使得σ= <
●解空间树
有 个叶子节点的子集树
2
If w[i,j]=1 and x[j]=x[i] then return False
3
return True
10
时间复杂度分析
算法的计算时间上界可由状态空间树内部节点的个数得到,n个节点的
图着色问题论述
图着色问题论述在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。
若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。
而若使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束。
贪心法它适用于解一些组合数较大的问题。
根据当前已有的信息就做出选择,而且一旦做出了选择,不管将来有什么结果,这个选择都不会改变。
换言之,贪心法并不是从整体最优考虑,它所做出的选择只是在某种意义上的局部最优。
【关键词】图着色回溯法贪心法1 图着色问题的分类1.1 回溯法回溯法是一种系统地搜索问题解的搜索算法。
它在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。
算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。
如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。
否则,进入该子树,继续按深度优先的策略进行搜索。
用回溯法解题的一般步骤:(1)描述解的形式,定义一个解空间,它包含问题的所有解。
(2)构造状态空间树。
(3)构造约束函数(用于杀死节点)。
1.2 贪心算法贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。
不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。
贪心算法不是对所有问题都能得到整体最优解,但对一些问题它能产生整体最优解或者是整体最优解的近似解。
贪心算法没有固定的算法框架,算法设计的关键是贪婪策略的选择。
一定要注意,选择的贪婪策略要具有无后向性,即某阶段状态一旦确定以后,不受这个状态以后的策略影响,也就是说某个状态以后的过程不会影响以前的状态,只与当前状态有关,也称为这种特性为无后效性。
因此,适应用贪婪策略解决的问题类型较少,对所采用的贪婪策略一定要仔细分析其是否满足无后效性。
图的着色问题是由地图的着色问题引申而来的:用m 种颜色为地图着色,使得地图上的每一个区域着一种颜色,且相邻区域颜色不同。
图的着色问题
顶点着色-基本概念
• K可着色:G的一个k顶点着色是指k种颜色1,2,…,k对于G各顶点的 可着色: 的一个k顶点着色是指k种颜色1,2,…,k对于G 1,2, 对于 一个分配,如果任意两个相邻顶点都分配到不同的颜色, 一个分配,如果任意两个相邻顶点都分配到不同的颜色,则称着 色是正常的。换句话说,无环图G的一个正常k顶点着色是把V 色是正常的。换句话说,无环图G的一个正常k顶点着色是把V分成 可能有空的)独立集的一个分类( 2,… k个(可能有空的)独立集的一个分类(V1,V2,…,Vk)。当G有一个 正常k顶点着色时,就成G 顶点可着色的。 正常k顶点着色时,就成G是k顶点可着色的。 • G的色数X(G)是指G为k可着色的k的最小值,若X(G)=k,则称G 的色数X 是指G 可着色的k的最小值, =k,则称G 色的。 是k色的。 • 事实上,如果我们将同色的顶点列入一个顶点子集,那么求X(G) 事实上,如果我们将同色的顶点列入一个顶点子集,那么求X 就转为求满足下列条件的最少子集数k 就转为求满足下列条件的最少子集数k: 两两子集中的顶点不同; (1)两两子集中的顶点不同; 子集中的两两顶点不相邻。 (2)子集中的两两顶点不相邻。 显然有: 为平凡图, =1; 显然有: (i)若G为平凡图,则X(G)=1; ii) 为偶图, (ii)若G为偶图,则X(G)=2 iii)对任意图G Δ+1(这里Δ (iii)对任意图G,有X(G)≤Δ+1(这里Δ表示为顶点 数最大值) 数最大值)
问题来源
图的着色
• 通常所说的着色问题是指下述两类问题: 通常所说的着色问题是指下述两类问题: • 1.给定无环图G=(V,E),用m种颜色为图中 的每条边着色,要求每条边着一种颜色, 的每条边着色,要求每条边着一种颜色,并 使相邻两条边有着不同的颜色, 使相邻两条边有着不同的颜色,这个问题称 为图的边着色问题。 为图的边着色问题。 • 2.给定无向图G=(V,E),用m种颜色为图中 的每个顶点着色,要求每个顶点着一种颜色, 的每个顶点着色,要求每个顶点着一种颜色, 并使相邻两顶点之间有着不同的颜色, 并使相邻两顶点之间有着不同的颜色,这个 问题称为图的顶着色问题。 问题称为图的顶着色问题。
实验四 回溯法(图的着色问题)
图的着色问题是由地图的着色问题引申而来的: 用m种颜色为地图着色,使得地图上的每一个 区域着一种颜色,且相邻区域颜色不同。 问题处理:如果连接,就可以把一 个区域图抽象为一个平面图。 地图(map)中地区的相邻关系,在图(graph) 中用边表示。
对应的邻接矩阵
0 0 1 2 3 4 0 1 1 0 1 1 1 0 1 0 1 2 1 1 0 1 0 3 0 0 1 0 1 4 1 1 0 1 0
class MGraph { public: MGraph(int v,int s); void mColoring(int m,int *x); //一维数组x,存放1~n个顶点的颜色 ~MGraph(); private: void NextValue(int k,int m,int *x); void mColoring (int k,int m,int *x); int **a; //二维数组a,存储图的邻接矩阵 int n,e; //n表示图的顶点数,e表示边数 };
}
void MGraph::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]==0) return; //已经试完所有颜色,没有可用颜色 for (int j=0; j<k; j++) if (a[k][j] && x[k] == x[j]) break;
无向图G
【实验内容与要求】
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
01 234 001 1 01 1 1 01 01 21 1 01 0 3001 01 41 1 01 0
class MGraph { public:
MGraph(int v,int s); void mColoring(int m,int *x); //一维数组x,存放1~n个顶点的颜色 ~MGraph(); private: void NextValue(int k,int m,int *x); void mColoring (int k,int m,int *x); int **a; //二维数组a,存储图的邻接矩阵 int n,e; //n表示图的顶点数,e表示边数 };
无向图G
【实验内容与要求】
图的着色问题:设G=(V,E)是一连通无向图,有3 种颜色,用这些颜色为G的各顶点着色,每个顶点着 一种颜色,且相邻顶点颜色不同。试用回溯法设计一 个算法,找出所有可能满足上述条件的着色法。
无向图G
无向图G
对应这个无向图的状态空间树应该是怎样的?
是一个完全3叉树,共6层
实验四 回溯法 — 图的着色问题
图的着色问题是由地图的着色问题引申而来的: 用m种颜色为地图着色,使得地图上的每一个 区域着一种颜色,且相邻区域颜色不同。
问题处理:如果把每一个区域收缩为一个顶点, 把相邻两个区域用一条边相连接,就可以把一
个区域图抽象为一个平面图。
地图(map)中地区的相邻关系,在图(graph )中用边表示。
//若(i, j)是图的边,且相邻结点k和j颜色相同 //发生冲突,选下一种颜色
if (j==k) return; //成功选择一种颜色返回 }while (1); //循环尝试颜色 }
运行结果:
谢谢观赏
递归回溯:
1. 为x[k]分配一个合法的颜色(即为第k个顶点分配颜色)。 2. 如果x[k]为0,表示当前没有适合的颜色,此方案不可行,返回。 3. 顶点k颜色分配成功后:
3.1如果k=n-1,表示所有顶点分到一个合法的颜色(完全着色);
输出x数组
3.2否则(还未完全着色)对k+1顶点进行着色(递归,向下一层搜索);
//x[k]=0 表示没有可用颜色,颜色从1开始编号
do { x[k]=(x[k]+1) % (m+1); //尝试下一种颜色 if (x[k]==0) return; //已经试完所有颜色,没有可用颜色 for (int j=0; j<k; j++) if (a[k][j] && x[k] == x[j]) break;
完
{
//得到图G的一种m-着色方案
全 着
for (int i=0; i<n; i++) cout << x[i] << ' ';
色
cout << endl;
}
else mColoring(k+1,m,x); //已经对前k个结点分配了颜色,尝试其余结 点(部分着色)
} while(1);
}
void MGraph::NextValue(int k,int m,int *x) { //本函数在[1,m]中为x[k]确定一个值最小的,且不与其邻接点冲突的颜色
4. 回到1,寻找下一个可行的方案
void MGraph:: mColoring(iຫໍສະໝຸດ t k,int m,int *x) {
do { NextValue(k,m,x); //为x[k]分配颜色
if (x[k]==0) break;
//x[k]=0表示当前没有适当的颜色,此着色方案不可行
if (k == n-1)