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

解题思路:

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

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

暴力枚举的代码:

 #include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
char str[];
int a[][],b[],c[][],visit[];
int main(){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
while(gets(str)){
memset(visit,,sizeof(visit));
memset(a,,sizeof(a));
memset(b,,sizeof(b));
memset(c,,sizeof(c));
if(str[]=='#') break;
else{
for(int i=;i<strlen(str);){
if(str[i]==' '){
i++;
continue;
}
int t=str[i++]-'A'+;
while(str[i]==' '){i++;}
i++;
while(i<strlen(str)){
if(str[i]==' '){
i++;
continue;
}
if(str[i]==';'){
i++;
break;
}
int k=str[i++]-'A'+;
a[t][k]=;
a[k][t]=;
}
}
}
int num=;
for(int i=;i<;i++){
int sum=;
for(int j=;j<;j++){
sum=sum+a[i][j];
}
if(sum){b[num++]=i;}
}
int minn=;
do{
int maxx=;
for(int i=;i<num;i++){
for(int j=;j<=;j++){
if(a[b[i]][j]){
for(int k=i+;k<;k++){
if(b[k]==j) maxx=max(maxx,k-i);
}
}
}
}
if(!visit[maxx]){
for(int i=;i<num;i++){
c[maxx][i]=b[i];
}
visit[maxx]=;
}
minn=min(minn,maxx);
}while(next_permutation(b,b+num));    //全排列函数。耗时,但是节省代码的长度时可用
for(int i=;i<num;i++){
printf("%c ",c[minn][i]+'A'-);
}
printf("-> %d\n",minn);
}
return ;
}

递归回溯的代码:

 #include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
char str[];
int minn,maxx,num;
int a[][],b[],c[],visit[],goal[]; void dfs(int n,int maxx){
if(n==num){
minn=maxx;
memcpy(goal,c,sizeof(c));
return;
}
for(int i=;i<num;i++){
if(!visit[b[i]]){
visit[b[i]]=;
c[n]=b[i];
int w=;
for(int j=;j<n;j++){
if(a[b[i]][c[j]]){
w=n-j;
break;
}
}
int max_w=max(maxx,w);
if(max_w<minn){
dfs(n+,max_w);
}
visit[b[i]]=;
}
}
} int main(){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
while(gets(str)){
memset(visit,,sizeof(visit));
memset(a,,sizeof(a));
memset(b,,sizeof(b));
memset(c,,sizeof(c));
if(str[]=='#') break;
else{
for(int i=;i<strlen(str);){
if(str[i]==' '){
i++;
continue;
}
int t=str[i++]-'A'+;
while(str[i]==' '){i++;}
i++;
while(i<strlen(str)){
if(str[i]==' '){
i++;
continue;
}
if(str[i]==';'){
i++;
break;
}
int k=str[i++]-'A'+;
a[t][k]=;
a[k][t]=;
}
}
}
num=;
for(int i=;i<;i++){
int sum=;
for(int j=;j<;j++){
sum=sum+a[i][j];
}
if(sum){b[num++]=i;}
}
minn=;
maxx=;
dfs(,);
for(int i=;i<num;i++)
printf("%c ",goal[i]+'A'-);
printf("-> %d\n",minn); }
return ;
}

提供几组测试数据:

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

递归回溯 UVa140 Bandwidth宽带的更多相关文章

  1. LeetCode || 递归 / 回溯

    呜呜呜 递归好不想写qwq 求“所有情况”这种就递归 17. Letter Combinations of a Phone Number 题意:在九宫格上按数字,输出所有可能的字母组合 Input: ...

  2. FZU - 2038 -E - Another Postman Problem (思维+递归+回溯)

    Chinese Postman Problem is a very famous hard problem in graph theory. The problem is to find a shor ...

  3. 40. 组合总和 II + 递归 + 回溯 + 记录路径

    40. 组合总和 II LeetCode_40 题目描述 题解分析 此题和 39. 组合总和 + 递归 + 回溯 + 存储路径很像,只不过题目修改了一下. 题解的关键是首先将候选数组进行排序,然后记录 ...

  4. UVA-140 Bandwidth (回溯+剪枝)

    题目大意:求一个使带宽最小的排列和最小带宽.带宽是指一个字母到其相邻字母的距离最大值. 题目分析:在递归生成全排列的过程中剪枝,剪枝方案还是两个.一.当前解不如最优解优时,减去:二.预测的理想解不必最 ...

  5. uva140 - Bandwidth

    Bandwidth Given a graph (V,E) where V is a set of nodes and E is a set of arcs in VxV, and an orderi ...

  6. 假回溯-uva140带宽

    题目链接:https://vjudge.net/problem/UVA-140 题解:这道题利用全排函数即可解决,但是这道题技巧性强,稍微不注意就会超时,一开始没有想起全排函数,自己写回溯全排超时了, ...

  7. C语言递归回溯法迷宫求解

    本例将随机产生一个10*10的迷宫输出后,在下面输出此迷宫的解法. 解法为从坐标(1,1)处进入,从(8,8,)出去,优先线路为先右后下再上最后为左. 不少人求解此题时运用的栈的相关知识,本例寻找线路 ...

  8. UVa140 Bandwidth 小剪枝+双射小技巧+枚举全排列+字符串的小处理

    给出一个图,找出其中的最小带宽的排列.具体要求见传送门:UVa140 这题有些小技巧可以简化代码的编写. 本题的实现参考了刘汝佳老师的源码,的确给了我许多启发,感谢刘老师. 思路: 建立双射关系:从字 ...

  9. [LeetCode] Sudoku Solver 解数独,递归,回溯

    Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by th ...

随机推荐

  1. 面试时,当你有权提问时,别客气,这是个逆转的好机会(内容摘自Java Web轻量级开发面试教程)

    前些天,我在博客园里写了篇文章,如何在面试中介绍自己的项目经验,收获了2千多个点击,这无疑鼓舞了我继续分享的热情,今天我来分享另外一个面试中的甚至可以帮助大家逆转的技巧,本文来是从 java web轻 ...

  2. css基础语法三

    []伪类选择器] 1.写法: 伪类选择器,在选择器后面,用:分隔,紧接伪类状态: eg : .a:link 2. 超链接的伪类状态: :link - 未访问状态 :visited - 已访问状态 :h ...

  3. python基础知识——基于python3.6

    语法糖 # # -*- coding: utf-8 -*- # #------------- # #--------- 语法糖--------------- # #------------------ ...

  4. 分布式框架Dubbo入门

    Dubbo简介 Dubbo是一个Alibaba开源额分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案.dubbo就是个服务框架,只有在分布式的时候,才有dubb ...

  5. 使用spring框架中的组件发送邮件

    首先进入自己的QQ邮箱,在设置中修改账户信息 然后来至底部  点击开启,再用手机发送对应信息到指定号码,然后点击我已发送  获取授权码  注意提示: 到这里,相信你已经开通了SMTP服务,这样就可以在 ...

  6. 小白必看Python视频基础教程

    Python的排名从去年开始就借助人工智能持续上升,现在它已经成为了第一名.Python的火热,也带动了工程师们的就业热.可能你也想通过学习加入这个炙手可热的行业,可以看看Python视频基础教程,小 ...

  7. VUE环境配置——运行Demo

    如果有Vue的Demo   不知道怎么运行的同学可以看这里 这里只讲Win下面环境配置 一.NodeJs安装 1.下载Windows 安装包(.msi),并安装https://nodejs.org/d ...

  8. .net core 同时实现网站管理员后台、会员、WebApi登录及权限控制

    我们在开网站信息系统时,常常有这样几个角色,如后台的管理员,前台的会员,以及我们各种应用的WebAPI 都需要进行登录操作及权限控制,那么在.net core如何进行设计呢. 首先我使用的是.net ...

  9. 制作代码模板的 LaTex 模板

    Tex 真的是一个用起来非常舒服的排版工具(对于排版要求高的人来说),去比赛前一天放弃了markdown转pdf来生成代码模板,现学Tex(其实美赛已经用过了:P). 推荐一个链接:TeX - Bea ...

  10. ELK 快速指南

    ELK 快速指南 概念 ELK 是什么 ELK 是 elastic 公司旗下三款产品 ElasticSearch .Logstash .Kibana 的首字母组合. ElasticSearch 是一个 ...