题意:给出一个n (n≤8) 个结点的图G和一个结点的排列,定义结点i的带宽 b(i) 为i和相邻结点在排列中的最远距离,而所有 b(i) 的最大值就是整个图的带宽,如图1所示。下面两个排列的带宽分别为6和5.具体来说图2左中各个结点的带宽分别为6,6,1,4,1,1,6,6,图2右中各个结点的带宽分别为5,3,1,4,3,5,1,4。(本段摘自《算法竞赛入门经典(第2版)》)
分析:直接暴力枚举结点的所有排列进行寻找答案即可。
代码:
#include <fstream>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <stack>
#include <sstream>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <vector>
#include <set>
#include <string>
#include <vector>
using namespace std;
const int maxn = 80 + 5, INF = 1e8;
string s, x, anss;
int l, tmp, ans;
int vv[30];
vector< int > v[30];
int dist(int a, int b)
{
int aa, bb;
for (int i = 0; i < x.size(); ++i)
if (x[i] == a + 'A')
aa = i;
else if (x[i] == b + 'A')
bb = i;
return abs(aa - bb);
}
int calc()
{
int res = 0, tmp;
for (int i = 0; i < 26; ++i)
if (v[i].size() != 0)
{
tmp = 0;
for (int j = 0; j < v[i].size(); ++j)
tmp = max(tmp, dist(i, v[i][j]));
if (tmp >= ans)
return INF;
res = max(res, tmp);
}
return res;
}
int main()
{
while (cin >> s, s != "#")
{
for (int i = 0; i < 30; ++i)
v[i].clear();
ans = INF;
x = "";
memset(vv, 0, sizeof(vv));
l = s.size();
for (int i = 0; i < l; ++i)
{
vv[s[i] - 'A'] = 1;
tmp = i + 2;
while (tmp < l && s[tmp] != ';')
{
v[s[i] - 'A'].push_back(s[tmp] - 'A');
v[s[tmp] - 'A'].push_back(s[i] - 'A');
vv[s[tmp] - 'A'] = 1;
++tmp;
}
i = tmp;
}
for (int i = 0; i < 30; ++i)
if (vv[i])
x += (char)(i + 'A');
sort(x.begin(), x.end());
do
{
tmp = calc();
if (tmp < ans)
{
ans = tmp;
anss = x;
}
} while (next_permutation(x.begin(), x.end()));
for (int i = 0; i < anss.size(); ++i)
printf("%c ", anss[i]);
printf("-> %d\n", ans);
}
return 0;
}