zoukankan      html  css  js  c++  java
  • 递归回溯 UVa140 Bandwidth宽带

    本题题意:寻找一个排列,在此排序中,带宽的长度最小(带宽是指:任意一点v与其距离最远的且与v有边相连的顶点与v的距离的最大值),若有多个,按照字典序输出最小的哪一个。

    解题思路:

      方法一:由于题目说结点的个数最多是8个,所以,最先想到的方法是暴力枚举,将所有的结点全排列,然后找到宽带长度最小的那一个,此方法不会超时。

      方法二:利用回溯法,将所有肯能的情况都遍历一遍,保存目前最短的宽带的长度minn,若当前的宽带长度大于minn,就进行剪枝,此题要注意,此题的结点不一定是从A开始的,所以要建立字母的映射,保存结点,同是注意输入时空格的处理。

    暴力枚举的代码:

     1 #include<stdio.h>
     2 #include<math.h>
     3 #include<string.h>
     4 #include<algorithm>
     5 #include<iostream>
     6 using namespace std;
     7 char str[100];
     8 int a[30][30],b[10],c[10][10],visit[10];
     9 int main(){
    10 //    freopen("in.txt","r",stdin);
    11 //    freopen("out.txt","w",stdout);
    12     while(gets(str)){
    13         memset(visit,0,sizeof(visit));
    14         memset(a,0,sizeof(a));
    15         memset(b,0,sizeof(b));
    16         memset(c,0,sizeof(c));
    17         if(str[0]=='#') break;
    18         else{
    19             for(int i=0;i<strlen(str);){
    20                 if(str[i]==' '){
    21                     i++;
    22                     continue;
    23                 }
    24                 int t=str[i++]-'A'+1;
    25                 while(str[i]==' '){i++;}
    26                 i++;
    27                 while(i<strlen(str)){
    28                     if(str[i]==' '){
    29                         i++;
    30                         continue;
    31                     }
    32                     if(str[i]==';'){
    33                         i++;
    34                         break;
    35                     }
    36                     int k=str[i++]-'A'+1;
    37                     a[t][k]=1;
    38                     a[k][t]=1;
    39                 }
    40             }
    41         }
    42         int num=0;
    43         for(int i=0;i<30;i++){
    44             int sum=0;
    45             for(int j=0;j<30;j++){
    46                 sum=sum+a[i][j];
    47             }
    48             if(sum){b[num++]=i;}
    49         }
    50         int minn=7;
    51         do{
    52             int maxx=0;
    53             for(int i=0;i<num;i++){
    54                 for(int j=1;j<=26;j++){
    55                     if(a[b[i]][j]){
    56                         for(int k=i+1;k<8;k++){
    57                             if(b[k]==j)    maxx=max(maxx,k-i);
    58                         }
    59                     }
    60                 }
    61             }
    62             if(!visit[maxx]){
    63                 for(int i=0;i<num;i++){
    64                     c[maxx][i]=b[i];
    65                 }
    66                 visit[maxx]=1;
    67             }
    68             minn=min(minn,maxx);
    69         }while(next_permutation(b,b+num));    //全排列函数。耗时,但是节省代码的长度时可用
    70         for(int i=0;i<num;i++){
    71             printf("%c ",c[minn][i]+'A'-1);
    72         }
    73         printf("-> %d
    ",minn);
    74     }
    75     return 0;
    76 }

    递归回溯的代码:

     1 #include<stdio.h>
     2 #include<math.h>
     3 #include<string.h>
     4 #include<algorithm>
     5 #include<iostream>
     6 using namespace std;
     7 char str[100];
     8 int minn,maxx,num;
     9 int a[30][30],b[10],c[10],visit[30],goal[10];
    10 
    11 
    12 void dfs(int n,int maxx){
    13     if(n==num){
    14         minn=maxx;
    15         memcpy(goal,c,sizeof(c));
    16         return;
    17     }
    18     for(int i=0;i<num;i++){
    19         if(!visit[b[i]]){
    20             visit[b[i]]=1;
    21             c[n]=b[i];
    22             int w=0;
    23             for(int j=0;j<n;j++){
    24                 if(a[b[i]][c[j]]){
    25                     w=n-j;
    26                     break;
    27                 }
    28             }
    29             int max_w=max(maxx,w);
    30             if(max_w<minn){
    31                 dfs(n+1,max_w);
    32             }
    33             visit[b[i]]=0;
    34         }
    35     }
    36 }
    37 
    38 int main(){
    39    // freopen("in.txt","r",stdin);
    40 //    freopen("out.txt","w",stdout);
    41     while(gets(str)){
    42         memset(visit,0,sizeof(visit));
    43         memset(a,0,sizeof(a));
    44         memset(b,0,sizeof(b));
    45         memset(c,0,sizeof(c));
    46         if(str[0]=='#') break;
    47         else{
    48             for(int i=0;i<strlen(str);){
    49                 if(str[i]==' '){
    50                     i++;
    51                     continue;
    52                 }
    53                 int t=str[i++]-'A'+1;
    54                 while(str[i]==' '){i++;}
    55                 i++;
    56                 while(i<strlen(str)){
    57                     if(str[i]==' '){
    58                         i++;
    59                         continue;
    60                     }
    61                     if(str[i]==';'){
    62                         i++;
    63                         break;
    64                     }
    65                     int k=str[i++]-'A'+1;
    66                     a[t][k]=1;
    67                     a[k][t]=1;
    68                 }
    69             }
    70         }
    71         num=0;
    72         for(int i=0;i<30;i++){
    73             int sum=0;
    74             for(int j=0;j<30;j++){
    75                 sum=sum+a[i][j];
    76             }
    77             if(sum){b[num++]=i;}
    78         }
    79         minn=8;
    80         maxx=0;
    81         dfs(0,0);
    82         for(int i=0;i<num;i++)
    83             printf("%c ",goal[i]+'A'-1);
    84         printf("-> %d
    ",minn);
    85 
    86     }
    87     return 0;
    88 }

    提供几组测试数据:

    A:FB;B:GC;D:GC;F:AGH;E:HD
    A:FB;B:GC;D:GC;F:AGH;E:H
    A:B;B:C;C:D;D:E;E:F;F:G;G:H
    A:B;B:C;C:D;D:E;E:F;F:G;G:H;H:A
    A:B;B:CE;C:D;D:E;E:F;F:G;G:H;H:A
    A:B;B:CE;C:DG;D:E;E:F;F:G;G:H;H:A
    A:BCDEFGH;B:ACDEFGH;C:ABDEFGH;D:ABCEFGH;E:ABCDFGH;F:ABCDEGH;G:ABCDEFH;H:ABCDEFG
    #

    答案:

    A B C F G D H E -> 3
    C D B G A F E H -> 2
    A B C D E F G H -> 1
    A B H C G D F E -> 2
    C D B E A F H G -> 2
    A B H C E G D F -> 3
    A B C D E F G H -> 7

  • 相关阅读:
    PHPStrom 设置终端字体大小
    PostgreSQL 9 夸库查询
    弹性布局
    sql中的 where 、group by 和 having 用法解析
    数据库面试中常问的几个问题
    SQL中 UNION 和 UNION ALL 操作符小结
    SQL里 inner JOIN、 left (OUTER) JOIN 、right (OUTER) JOIN、 full (OUTER) JOIN 之间的区别
    MYSQL中LIMIT用法
    Java集合框架小结
    jQuery$.each循环遍历详解,各种取值对比,$.each遍历数组、对象、Dom元素、二维数组、双层循坏、类json数据等等
  • 原文地址:https://www.cnblogs.com/muziqiu/p/7325983.html
Copyright © 2011-2022 走看看