本题题意:寻找一个排列,在此排序中,带宽的长度最小(带宽是指:任意一点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. PHP(一)OOP基础

    [面向过程&面向对象] 1.面向过程:专注于解决一件事情的过程.最大的特点,是有一个个函数来实现功能需求 2.面向对象:专注于有哪一个对象来实现这个功能,最大的特点,时产生一个个具有属性和方法 ...

  2. indexed database IndexedDB

    Indexed Database API 目的是提供一个可供javascript存储和检索对象,并且还能进行查询,搜索等数据库操作   设计为几乎完全异步,因此绝大部分操作都稍后执行,因此每次操作都应 ...

  3. NFC (Near Filed Communication)

    NFC的用途:近场通信(Near Field Communication,NFC),又称近距离无线通信,是一种短距离的高频无线通信技术,允许电子设备之间进行非接触式点对点数据传输(在十厘米内)交换数据 ...

  4. 使用Jquery.js框架和CSS3实现3D相册的制作

    有关3D相册的制作主要包括以下几个知识点: 1.有关图片的位置摆放,也就是一个相对定位绝对定位的使用: 2.有关CSS3中transform属性的使用(transform-style: preserv ...

  5. phpcms 的getcache()函数

    一直没有去研究phpcms 的getcache()函数是干嘛的,今天有空去看了一下,原来就那样. 1 function getcache($name, $filepath='', $type='fil ...

  6. .Net中的装箱和拆箱

    装箱(boxing)和拆箱(unboxing)是.NET提出得新概念!.NET的所有类型都是由基类System.Object继承过来的,包括最常用的基础类型:int, byte, short,bool ...

  7. 引用reference作用域scope闭包closure上下文context用法

    引用(reference).作用域(scope).闭包(closure)以及上下文(context)是JavaScript重中之重的基础,也是学习好JavaScript的基础.在这里我以浅显的理解给大 ...

  8. Python待分析的模块

    fcntl 文件控制模块 http://docs.python.org/2.7/library/fcntl.html#module-fcntl struct 二进制文本处理模块 http://docs ...

  9. 小程序基于疼讯qcloud的nodejs开发服务器部署

        腾讯,疼讯,很疼. 请慎重看腾讯给出的文档,最好做一个笔记. 我只能说我能力有限,在腾讯云小程序的文档中跳了n天. 最后还是觉得记录下来,以防止我的cpu过载给烧了. 此文档是对<小程序 ...

  10. vue初级知识总结

    从我第一篇博客的搭建环境开始,就开始学习vue了,一直想将这些基本知识点整理出来,但是一直不知如何下手,今天刚好实战了两个小demo,所以就想趁这机会将以前的一起整理出来,这是vue最基础的知识,我有 ...