这道题在写以前必定要把题目读懂,笔者在设计代码时就对题意产生了错误的理解,好在后来这个错误被纠正了。node
这道题最主要的点就是对解答树遍历而且回溯,也就是《算法竞赛入门经典》中所提到的“剪枝”。递归的主体是生成结点的全排列,而回溯操做简单来讲就是在这个递归的基础上添加的一个判断。c++
先说生成全排列递归的操做,生成全排列就是在现有数组的基础上对数组进行新元素的插入,每次插入都会对已有数组进行遍历,若是发现新插入的元素在前面的数组中已经出现过,那么就跳过剩余操做插入下一个元素,递归的结束条件就是当前数组的长度与给出数组的长度相同。算法
再说回溯操做,程序中添加了一个变量MINB来记录当前全部排列中最小的带宽,每当数组中新添加了一个元素,就计算该元素(结点)与它相邻的结点的距离,若是此距离超过了最小带宽,那么就不用再遍历下去了,直接回溯。数组
须要提到的是,程序中图是使用邻接矩阵存储的,不过在把代码写完后,笔者发现或许使用邻接表存储会更加方便。函数
1 #include <bits/stdc++.h>
2
3 using namespace std; 4
5 /**************** 6 UVa140(带宽) 7 ***************/
8
9 const int MAX = 8; 10
11 int node[MAX]; 12 //用来记录带宽最小的结点序列
13 int minB[MAX]; 14 //邻接矩阵
15 int buf[MAX][MAX]; 16 int MAXL = 0;//带宽
17 int MINB = 99999;//最小带宽 18
19 //该函数是求排列的带宽的 20 //n:结点个数(字符数组长度) 21 //cur:当前位置
22 int BandWidth(int n){ 23 int cur = 0, i = 0, bnw = 0,j; 24 while(i < n && cur < n){ 25 int k = node[cur]; 26 //寻找相邻结点
27 if(buf[k][i]){ 28 for(j = 0; j < n; j++){ 29 //在结点序列中寻找相邻结点
30 if(node[j] == i){ 31 bnw = max(abs(j-cur), bnw); 32 } 33 } 34 } 35 //某个结点遍历结束
36 if(i == n-1){ 37 i = 0; 38 cur++; 39 continue; 40 } 41 i++; 42 } 43 return bnw; 44 } 45
46 void solve(int n, int cur) 47 { 48 if(cur == n){ 49 MAXL = BandWidth(n); 50 if(MINB > MAXL){ 51 for(int i = 0; i < n; i++){ 52 minB[i] = node[i]; 53 } 54 MINB = MAXL; 55 } 56 } 57 else{ 58 for(int i = 0; i < n; i++){ 59 int ok = 1; 60 for(int j = 0; j < cur; j++) 61 if(node[j] == i) ok = 0; 62 if(ok){ 63 int tmp = 0; 64 //寻找相邻结点
65 for(int j = 0; j < n; j++){ 66 if(buf[i][j]){ 67 //遍历当前数组有没有相邻结点
68 for(int k = 0; k < cur; k++) 69 if(node[k] == j) 70 tmp = MINB - (cur - k); 71 } 72 if(tmp < 0) return; 73 } 74 node[cur] = i; 75 solve(n, cur+1); 76 } 77 } 78 } 79
80 } 81
82 int main() 83 { 84 //n:结点数
85 int n = 0; 86 cin >> n; 87 //x,y是边的两条结点
88 char x, y; 89 memset(buf, 0, sizeof(buf)); 90 //构建邻接矩阵
91 while(true){ 92 cin >> x; 93 cin >> y; 94 if(x == '#' && y == '#') break; 95 buf[x-65][y-65] = 1; 96 buf[y-65][x-65] = 1; 97 } 98 solve(n, 0); 99 //输出结果
100 for(int i = 0; i < n; i++){ 101 printf("%c", minB[i]+65); 102 } 103 printf("\n"); 104 printf("%d", MINB); 105 return 0; 106 }
在编写代码时以为代码还不够精简,或许还有优化空间。优化
运行结果为:spa
8 A B A F B C B G C D D E D G E H F G F H # # ABCFGDHE 3