递归回溯 UVa140 Bandwidth宽带

本题题意:寻找一个排列,在此排序中,带宽的长度最小(带宽是指:任意一点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宽带的更多相关文章
- LeetCode || 递归 / 回溯
呜呜呜 递归好不想写qwq 求“所有情况”这种就递归 17. Letter Combinations of a Phone Number 题意:在九宫格上按数字,输出所有可能的字母组合 Input: ...
- 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 ...
- 40. 组合总和 II + 递归 + 回溯 + 记录路径
40. 组合总和 II LeetCode_40 题目描述 题解分析 此题和 39. 组合总和 + 递归 + 回溯 + 存储路径很像,只不过题目修改了一下. 题解的关键是首先将候选数组进行排序,然后记录 ...
- UVA-140 Bandwidth (回溯+剪枝)
题目大意:求一个使带宽最小的排列和最小带宽.带宽是指一个字母到其相邻字母的距离最大值. 题目分析:在递归生成全排列的过程中剪枝,剪枝方案还是两个.一.当前解不如最优解优时,减去:二.预测的理想解不必最 ...
- 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 ...
- 假回溯-uva140带宽
题目链接:https://vjudge.net/problem/UVA-140 题解:这道题利用全排函数即可解决,但是这道题技巧性强,稍微不注意就会超时,一开始没有想起全排函数,自己写回溯全排超时了, ...
- C语言递归回溯法迷宫求解
本例将随机产生一个10*10的迷宫输出后,在下面输出此迷宫的解法. 解法为从坐标(1,1)处进入,从(8,8,)出去,优先线路为先右后下再上最后为左. 不少人求解此题时运用的栈的相关知识,本例寻找线路 ...
- UVa140 Bandwidth 小剪枝+双射小技巧+枚举全排列+字符串的小处理
给出一个图,找出其中的最小带宽的排列.具体要求见传送门:UVa140 这题有些小技巧可以简化代码的编写. 本题的实现参考了刘汝佳老师的源码,的确给了我许多启发,感谢刘老师. 思路: 建立双射关系:从字 ...
- [LeetCode] Sudoku Solver 解数独,递归,回溯
Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by th ...
随机推荐
- C++ 随机生成一个(0,1)之间的小数
double p; ]; memset(s,,sizeof(s)); s[]='; s[]='.'; ;i<;i++) { s[i]=rand()%+'; } p=atof(s); cout & ...
- Vue js 的生命周期详解
Vue 实例的生命周期 Vue 实例有一个完整的生命周期,也就是从开始创建.初始化数据.编译模板.挂载Dom→渲染.更新→渲染.卸载等一系列 过程,我们称这是 Vue 的生命周期.通俗说就是 Vue ...
- linux-mkdir
mkdir mkdir : 可以用来创建目录,如果不加创建路径即在本路径下创建一个新的指定的目录,否则即在给出的路径下创建目录. 目录创建:目录名尽量见名知意,根据不同需要分层创建,尽量避免在同一目录 ...
- Android 异步消息处理机制前篇(一):深入理解ThreadLocal
版权声明:本文出自汪磊的博客,转载请务必注明出处. ThreadLocal简介 ThreadLocal是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,数据存储以后,只有在指定线程中可以获 ...
- [转载] ZooKeeper原理及使用
转载自http://www.wuzesheng.com/?p=2609 ZooKeeper是Hadoop Ecosystem中非常重要的组件,它的主要功能是为分布式系统提供一致性协调(Coordina ...
- 【RabbitMQ+Python入门经典】兔子和兔子窝 笔记
RabbitMQ工业级的消息队列服务器. 兔子和兔子窝 动机来源:从生产环境的电子邮件处理流程当中分支出一个特定的离线分析流程. 解决方案1: 开始使用MySQL处理,将要处理的东西放在表里面,另一个 ...
- swizzle method 和消息转发机制的实际使用
我的工程结构,如图 1-0 图 1-0 在看具体实现以前,先捋以下 实现思路. ViewController 中有一个-(void)Amethod;A方法. -(void)Amethod{ NSLo ...
- javaweb-番外篇-Commons-FileUpload组件上传文件
一.Commons-FileUpload简介 Commons-FileUpload组件 Commons是Apache开放源代码组织的一个Java子项目,其中的FileUpload是用来处理HTTP文件 ...
- Science发表的超赞聚类算法
作者(Alex Rodriguez, Alessandro Laio)提出了一种很简洁优美的聚类算法, 可以识别各种形状的类簇, 并且其超参数很容易确定. 算法思想 该算法的假设是类簇的中心由一些局部 ...
- SimpleMarkdown - 一款简单的Markdown编辑器
源码地址: https://github.com/zhuangZhou/SimpleMarkdown 预览地址: http://hawkzz.com:8000 作者网站:http://hawkzz.c ...