递归回溯 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 ...
随机推荐
- Windows环境下多线程编程原理与应用读书笔记(7)————事件及其应用
<一>事件 事件主要用于线程间传递消息,通过事件来控制一个线程是处于执行状态还是处于挂起状态. 事件和互斥量之间的差别: 事件主要用于协调两个或者多个线程之间的动作,使其协调一致,符合逻辑 ...
- css英文字符或者数字不换行的问题
table-layout:fixed; word-break: break-all; overflow:hidden;
- JavaNIO阻塞IO
package com.java.NIO; import java.io.IOException; import java.net.InetSocketAddress; import java.nio ...
- Hiberante知识点梳理
Hibernate简介 Hibernat是一个ORM(关系映射)框架,对JDBC访问数据库的操作进行了简化,并且将数据库表中的字段和关系映射为对象,简化了对数据库的操作. 使用方法 读取并解析配置文件 ...
- spring+struts2+hibernate整合
web.xml需要配置 <context-param> <param-name>contextConfigLocation</param-name> <par ...
- Array类的Sort()方法
刚复习了Array类的sort()方法, 这里列举几个常用的,和大家一起分享. Array类实现了数组中元素的冒泡排序.Sort()方法要求数组中的元素实现IComparable接口.如System. ...
- java 分页导出百万级数据到excel
最近修改了一个导出员工培训课程的历史记录(一年数据),导出功能本来就有的,不过前台做了时间限制(只能选择一个月时间内的),还有一些必选条件, 导出的数据非常有局限性.心想:为什么要做出这么多条件限制呢 ...
- C语言控制流语句
title: 2017-10-18控制流 tags: binsearch else-if, shellsort, insertsort grammar_cjkRuby: true --- 前段时间忙着 ...
- [转载] zookeeper工作原理、安装配置、工具命令简介
转载自http://www.cnblogs.com/kunpengit/p/4045334.html 1 Zookeeper简介Zookeeper 是分布式服务框架,主要是用来解决分布式应用中经常遇到 ...
- API设计相关
来自HeroKu的HTTP API 设计指南 http://get.jobdeer.com/343.get https://github.com/interagent/http-api-design ...