您的位置:首页 > 其它

【算法竞赛入门经典】回溯法与最优性剪枝条 例题7-6 UVa140

2018-03-05 11:05 369 查看

【算法竞赛入门经典】回溯法与最优性剪枝条 例题7-6 UVa140

【算法竞赛入门经典】回溯法与最优性剪枝条 例题7-6 UVa140
例题UVa140

分析
储存结构

样例实现代码

结果

例题UVa140



Input



Output



Sample Input

A:FB;B:GC;D:GC;F:AGH;E:HD

#

Sample Output

A B C F G D H E -> 3

分析

一眼能看出来的做法:枚举所有排列的可能性,分别计算带宽之后选取最小的方案。

显然枚举全部可能的话时间效率可能不尽人意。那么该如何剪枝呢。当你计算出当前最优解ans之后,若是枚举出一个可能情况后,计算中出现了比ans更大的值,那么肯定不可能比它小了,这种情况应该果断减掉。

如果分别存储每个节点的相邻节点的话,那么如果当前节点的未计算个数大于ans的话,那么无论任何情况下,都不会有比ans更小的解了,也应当减掉。(代码中未写出)

储存结构

从方便的目的来考虑,将字母转化为数字记录。使用一个vector记录每个pair,每个pair中是一个边的两个点编号。即使用其记录了每个边。这样每次只需要遍历所有的边即可。

position[]用于记录某个点在当前情况序列中排在第几个。

样例实现代码

#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
#define maxn 30
using namespace std;
vector<pair<int, int> >dat;
vector<int>chars;
int l[maxn], bestsit[maxn], position[maxn];
int main() {
char pin[1000];
while (scanf("%s", pin) == 1 && pin[0] != '#') {
int n = 0;
int a = 0, b = 0, ans = 10, bandwidth = 0;
chars.clear();
for (char c = 'A'; c <= 'Z'; c++) {
if (strchr(pin, c)) {
chars.push_back(c - 'A');
n++;
}
}
int length = strlen(pin);
dat.clear();
while (1) {
while (a<length&&pin[a] != ':')
a++;
if (a == length)
break;
while (b<length&&pin[b] != ';')
b++;
for (int i = a + 1; i<b; i++) {
dat.push_back(make_pair(pin[a - 1] - 'A', pin[i] - 'A'));
}
a++;
b++;
}
for (int i = 0; i<n; i++)
l[i] = chars[i];
do {
bandwidth = 0;
for (int i = 0; i<n; i++)
position[l[i]] = i;
for (int i = 0; i<dat.size(); i++) {
bandwidth = max(bandwidth, abs(position[dat[i].first] - position[dat[i].second]));
if (bandwidth>ans)
break;
}
if (bandwidth<ans) {
memcpy(bestsit, l, sizeof(l));
ans = bandwidth;
}
} while (next_permutation(l, l + n));
for (int i = 0; i<n; i++)
cout << (char)(bestsit[i] + 'A') << " ";
cout << "-> " << ans << endl;
}
return 0;
}


结果

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐