zoukankan      html  css  js  c++  java
  • UVA 140 Bandwidth (dfs 剪枝 映射)

    题意:

    给定一个n个结点的图G和一个结点的排列, 定义结点i的带宽b(i)为i和相邻结点在排列中的最远距离, 所有b(i)的最大值就是这个图的带宽, 给定G, 求让带宽最小的结点排列。

    给定的图 n <=8, 字母包含A~Z

    上图是两种排列, 图1 各个b(i) 为 6 6 1 4 1 1 6 6 最大值为6  图2 b(i)为 5 3 1 4 3 5 1 4 最大值为 5

    本图答案应为 A B C F G D H E    

    b(i)为3  3  3  3  2  3  3  3, 最大值为3.

    分析:

    首先本题输入格式是那种给出一行,然后比较繁琐的题目, 所以可以考虑先读入一行再进行处理会比边读边处理好一点。

    读入后第一要确认的就是这个图包含哪些字母, 因为本题需要全排列并按字典序输出, 所以最好把字母先映射为id, 这里使用了,strchr(const char* , char), 该函数可返回字符串中char第一次出现的位置, 不包含该ch则返回NULL。

    并把编号由大到小写到letter中, 那么只需要生成这些id的全排列, 就能知道这些字母的全排列。

    第二步是建图, 把输入中有用的信息提炼出来, 那么就可以用邻接矩阵建图了,不使用邻接表是因为本题输入会有重边。

    然后就可以dfs生成全排列了, 这里我只用了一个剪枝, 就是搜索到结点u时, 如果u有m个相邻结点,而且有last(m-已经选中的结点)个还没被我前面的递归选中, 那么如果last > 当前最优带宽k, 就可以剪枝。 因为对于结点u而言, 最理想情况是这last个结点紧跟在u后, 这样结点带宽为m, 如果m >= 目前已经找到最优带宽k , 剪枝是合理的。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 char input[3000];
     4 int id[256], letter[30], node[30], temp[30], best_wid[30];
     5 int adj[10][10];
     6 int cnt = 0;
     7 int min_wid = 1e5;
     8 bool vis[30];
     9 int pos[30];
    10 void dfs(int dep){
    11     if(dep == cnt){
    12         int t_wid = -1, pp_wid = -1;
    13         for(int i = 0; i < cnt; i++){
    14             pp_wid = -1;
    15             for(int j = 0; j < cnt; j++){
    16             if(adj[i][j]){
    17                     pp_wid = max(pp_wid, abs(pos[i] - pos[j]) );
    18                 }
    19             }
    20             t_wid = max(t_wid, pp_wid);
    21         }
    22         if(t_wid < min_wid){
    23             for(int i = 0; i < cnt; i++){
    24                 best_wid[i] = temp[i];
    25             }
    26             min_wid = t_wid;
    27         }
    28     }
    29     else{
    30         for(int i = 0; i < cnt; i++){
    31             if(!vis[i]){
    32                 int last = 0;
    33                 for(int j = 0; j < cnt; j++)
    34                 {
    35                     if(adj[i][j]){
    36                         int ok = 1;
    37                         for(int k = 0; k < dep; k++){
    38                             if(temp[k] == j) { ok = 0; break;}
    39                         }
    40                         if(ok) last ++;
    41                     }
    42                 }
    43                 if(last >= min_wid)
    44                     continue;
    45                 vis[i] = 1;
    46                 temp[dep] = i;
    47                 pos[temp[dep]] = dep;
    48                 dfs(dep+1);
    49                 vis[i] = 0;
    50             }
    51         }
    52     }
    53 }
    54 int main()
    55 {
    56     while(scanf("%s", input) && input[0] != '#'){
    57         memset(adj,0,sizeof(adj));
    58         cnt = 0,  min_wid = 1e5;
    59         for(char a = 'A'; a <= 'Z'; a++){
    60             if(strchr(input, a)){
    61                 id[a] = cnt++;
    62                 letter[id[a]] = a;
    63             }
    64         }
    65         int len = strlen(input), p=0, q=0;
    66         while(1){
    67             while(p < len && input[p]!= ':')
    68                 p++;
    69             if(p == len) break;
    70             while(q < len && input[q]!= ';')
    71                 q++;
    72 //             p定位: q定位;
    73             for(int i = p+1; i < q; i++){
    74                 adj[id[input[p-1]]][id[input[i]]] = 1;
    75                 adj[id[input[i]]][id[input[p-1]]] = 1;
    76             }
    77             p++, q++;
    78         }
    79 
    80         dfs(0);
    81         for(int i = 0; i < cnt; i++){
    82             printf("%c ", letter[best_wid[i]]);
    83         }
    84         printf("-> %d
    ", min_wid);
    85     }
    86     return 0;
    87 }
  • 相关阅读:
    标准库:Number 对象
    标准库:Boolean 对象
    标准库:包装对象
    标准库:Array 对象
    git的基本操作
    子查询、联结、约束、索引
    sql基础、检索、过滤数据
    聚合函数和分组数据-GROUP BY、HAVING
    长期更新~java学习过程中遇到的英语单词
    3.(155)最小栈
  • 原文地址:https://www.cnblogs.com/Jadon97/p/7155717.html
Copyright © 2011-2022 走看看