UVa140(带宽)

这道题在写以前必定要把题目读懂,笔者在设计代码时就对题意产生了错误的理解,好在后来这个错误被纠正了。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
相关文章
相关标签/搜索