算法5.旅行售货员问题和数独游戏。
来源:互联网 发布:qrcode 生成算法 编辑:程序博客网 时间:2024/05/17 03:26
- 某售货员要到4个城市去推销商品,已知各城市之间的路程,如右图所示。请问他应该如何选定一条从城市1出发,经过每个城市一遍,最后回到城市1的路线,使得总的周游路程最小?并分析所设计算法的计算时间复杂度。
(1) 算法设计思路
解向量:{1,2,3,4,1}{1,2,4,3,1,}{1,3,4,2,1}{1,3,2,4,1}{1,4,2,3,1}{1,4,3,2,1}
解空间:是一个排序树,树的叶结点个数为(n-1)!=6
上界函数:当前第一次所得到的值作为约束条件,然后比该值小时更新约束值
int n,图的顶点数,int[] x 当前解,int[] bestx 当前最优解,int[][] a 图的邻接矩阵,int cc 当前费用,int bestc 当前最优值,No 无边标记
(2) 算法实现的伪代码及其计算时间复杂度分析
求解旅行售货员问题的算法back(int t)
输入:t为当前城市的个数
输出:最短路径和其对应值
s1: If (t=n){s2: if (a[x[n-1]][x[n]]!=No&&a[x[n]][1]!=No && (cc+a[x[n-1]][n]+a[x[n]][1])<bestc || bestc=No){s3: for (inti =1 to n )best[i]=x[i]s4: bestc=cc+ a[x[n-1]][n]+a[x[n]][1]s5: }s6: else{s7: for (inti =t to n){s8: if(a[x[t-1]][i]!=No && (cc+a[x[n-1]][n]+a[x[n]][1]<bestc || bestc =No)){s9: swap(x[t],x[i]) ;s10: cc+=a[x[t-1]][t];s11: back(t+1)s12: cc-=a[x[t-1]][t]s13: swap(x[t],x[i])s14: }s15: }
算法fucntionA的计算时间复杂度分析:O(n!)
(3) 实验代码及运行结果
public class TSP { static int[] x = new int[5]; static int[] bestx = new int[5]; static int[][] a = new int[5][5]; static int cc = 0; static int no = 10000; static int bestc = no; static int n = 4; static void back(int i) { if (i == n) { if (a[x[n - 1]][x[n]] != 0 && a[x[n]][1] != 0 && (cc + a[x[n - 1]][x[n]] + a[x[n]][1] < bestc || bestc == 0)) { for (int j = 1; j <= n; j++) bestx[j] = x[j]; bestc = cc + a[x[n - 1]][x[n]] + a[x[n]][1]; } } else { for (int j = i; j <= n; j++) { // 是否可进入x[j]子树? if (a[x[i - 1]][x[j]] != 0 && (cc + a[x[i - 1]][x[i]] < bestc || bestc == 0)) { // 搜索子树 // swap(x[i], x[j]); int temp1 = x[i]; x[i] = x[j]; x[j] = temp1; cc += a[x[i - 1]][x[i]]; // 当前费用累加 back(i + 1); // 排列向右扩展,排列树向下一层扩展 cc -= a[x[i - 1]][x[i]]; // swap(x[i], x[j]); int temp2 = x[i]; x[i] = x[j]; x[j] = temp2; } } } } // private static void swap(int i, int j) { // // TODO Auto-generated method stub // int temp = i; // i = j; // j = temp; // } public static void main(String[] args) { a[1][1] = no; a[1][2] = 30; a[1][3] = 6; a[1][4] = 4; a[2][1] = 30; a[2][2] = no; a[2][3] = 5; a[2][4] = 10; a[3][1] = 6; a[3][2] = 5; a[3][3] = no; a[3][4] = 20; a[4][1] = 4; a[4][2] = 10; a[4][3] = 20; a[4][4] = no; for (int i = 0; i <= 4; i++) x[i] = i; // x[1]=1; // x[2]=3;x[3]=2;x[4]=4; back(2); System.out.print("最优路劲为:"); for (int i = 1; i <= 4; i++) System.out.print(bestx[i]+"->"); System.out.println(x[1]); System.out.println("最小值为"+bestc); } }
//
//
(4) 体会
用回溯算法搜索排列树的算法框架可以描述为
void back(int t){if (t>n) output(x);else for (inti =t,i<n;i++){swap(x[t],x[i]);if( contriant(t)&&bound(t)) back(t+1)swap(x[t],x[i])}}
- 数独游戏:九宫格是在81个格子(9×9)中,要满足以下条件:① 每个横行和竖列中的9个格子都包含数字1~9,且不重复;② 每个黑色粗实线围住的9个格子(3×3)都包含数字1~9,且不重复。如图所示:
要求:找出给定数字的九宫格。
输入:输入9行9列81个数字,其中0表示要填的数字。
输出:输出满足条件的九宫格。
某测试样例如下:
(1) 算法设计思路
数独游戏是N后问题的变形版本。将n*n看成二维矩阵,行i列j,解空间是完成n叉树。
先判断要变化的数是否为0,如果为0,在行,列和小九宫格中判断有没有相同数字,有相同数字则+1,直到9,如果不为0,直接变化下一个数。
(2) 算法实现的伪代码及其计算时间复杂度分析
求解数独游戏的算法back(int i,int j)
输入:数组 的行i,列j
输出:满足条件的九宫格
s16: if(i=8并且j=9){s17: 输出满足条件的九宫格s18: }s19: if (j=9){s20: j=0;i++s21: } s22: if (x[i][j]=0)s23: for (int n=1 to 9){s24: if (判断是否在行,列,小九宫格中出现重复的值){s25: x[i][j]=n;s26: back(i,j+1)s27: x[i][j]=0;s28: }s29: else back(i,j+1)
算法fucntionB的计算时间复杂度分析:O(n^n)
(3) 实验代码及运行结果
public class 数独游戏 { static int[][] bestx = new int[9][9]; static int[][] x = { { 0, 6, 1, 0, 3, 0, 0, 2, 0 }, { 0, 5, 0, 0, 0, 8, 1, 0, 7 }, { 0, 0, 0, 0, 0, 7, 0, 3, 4 }, { 0, 0, 9, 0, 0, 6, 0, 7, 8 }, { 0, 0, 3, 2, 0, 9, 5, 0, 0 }, { 5, 7, 0, 3, 0, 0, 9, 0, 0 }, { 1, 9, 0, 7, 0, 0, 0, 0, 0 }, { 8, 0, 2, 4, 0, 0, 0, 6, 0 }, { 0, 4, 0, 0, 1, 0, 2, 5, 0 }, };; static int cc = 0; static int bestc; static void back(int i, int j) { if (i == 8 && j == 9) { for (int a = 0; a <= 8; a++) for (int b = 0; b <=8; b++) bestx[a][b] = x[a][b]; return; } //如果j=9,则重置j,然后行+1 if (j == 9) { j = 0; i++; } if (x[i][j] == 0) for (int n = 1; n < 10; n++) { if (!boo(i, j, n)) {//判断是否在行,列,小九宫格中出现重复的值 x[i][j] = n; back(i, j + 1); x[i][j] = 0; } } else back(i, j + 1); } //判断是否在行,列,小九宫格中出现重复的值 static boolean boo(int i, int j, int k) { int m = i / 3; int n = j / 3; for (int a = 0; a < 9; a++) { //判断行 if (k == x[i][a]) return true; //判断列 if (k == x[a][j]) return true; //判断小九宫格 if (k == x[3 * m + a / 3][3 * n + a % 3]) return true; } return false; } public static void main(String[] args) { System.out.println("test"); back(0, 0); System.out.println("test"); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (j < 8) System.out.print(bestx[i][j] + " "); else { System.out.println(bestx[i][j]); } } } } }
/
(4) 体会
回溯算法一般都有一个套路,先找出问题的解空间,再思考回溯方法。
用回溯算法搜索子集树的一般算法可以描述为:
void back(int i){ if (i>n) output(x); else for (int j=0 to n){ x[t]=i, if (constraint(i)&&bound(i)) back(i+1) } }
0 0
- 算法5.旅行售货员问题和数独游戏。
- 算法学习1:旅行售货员问题
- 算法笔记 //11_旅行售货员问题
- 旅行售货员问题
- 旅行售货员问题
- 旅行售货员问题1
- 旅行售货员问题
- 旅行售货员问题
- 旅行售货员问题
- 旅行售货员问题
- ZQUOJ1927旅行售货员问题
- 旅行售货员问题
- 算法java实现--回溯法--旅行售货员问题--排列树
- 算法java实现--分支限界法--旅行售货员问题
- 旅行售货员问题(c++)
- 回溯法----旅行售货员问题
- 旅行售货员问题(回溯法)
- 双调旅行售货员问题
- 自己做的一个WIFI模块+app,监控蓄电池电量
- 通过poi获取到了商店的地理位置之后,如何获取商店的详细信息。是需要商店提供还是地图提供
- Android studio无法运行项目
- android 手机之间(机顶盒之间) 应用的交互(服务)
- Python 中序列的索引与分片
- 算法5.旅行售货员问题和数独游戏。
- El表达式里面的对象
- oracle 11g 一直提示 严重: 监听程序未启动或数据库服务未注册到该监听程序。启动
- 公司的app在魅族4 flyme5.1上打开就黑屏
- 数据库中的查询语句
- 大牛请进,Android音视频聊天各种实现方式问题
- VMware安装mac问题
- Matlab 3.接上回 reshape 函数,矩阵的变维,实现矩阵的再分割和再拼接,多维转化。
- Araxis Merge对比软件工具