题目意思:给定n个节点,(n<=8),节点的编号为A~Z 来表示,要求找到一个节点的序列,使得该序列最大的节点的Bandwidth为所有序列中的最小值,(节点的Bandwidth是指和它所连接的点中和它距离最大的值)。
解题思路:由于最多只有8个节点,那么可以枚举这个解空间的所有情况,然后找到其中的最有解并且记录下它的节点顺序,那么我们可以通过求全排列的方法去一一枚举这些排列
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <algorithm>
using namespace std;
const int MAXN = 100000;
int k, cur, ans;
int vis[8];//存储节点的编号,通过编号来映射节点
int mark[30][30]; //用来标记节点和哪些节点有连接
int Minsum[MAXN][8];//用来记录每一个排列的节点的顺序
int Min;
//计算最小值的函数
void Minfun() {
int tempmax[8];//临时存储每一个点的最大值
int T, Tmax = 0;//T存储当前节点和另外节点的距离,Tmax存储一个点中的最大距离(后面求一个排列的最大值)
memset(tempmax, 0, sizeof (tempmax)); //初始话为0
for (int i = 0; i < k; i++) {//枚举这个序列的点
Tmax = 0;
for (int j = 1; j <= 26; j++) {
if (mark[vis[i]][j]) {//找打一个点的匹配点的最大的值
for (int t = 0; t < k; t++) {//找匹配点的位置
if (j == vis[t]) {
T = abs(i - t); //找到位置的距离
break;
}
}
if (Tmax < T)
Tmax = T;
}
}
tempmax[i] = Tmax;
}
Tmax = 0;
for (int i = 0; i < k; i++) {//求出该种排列的最大值
if (Tmax < tempmax[i]) {
Tmax = tempmax[i];
}
}
if (Min > Tmax) {//更新Min的值
ans = cur;//记录位置
Min = Tmax;
}
}
//处理函数
void solve() {
Min = 100000000;
cur = 0;
for (int i = 0; i < k; i++)//必须先保存到Minsum[0]里,不然调用了next_permutation(vis, vis + k)将直接跳到下一个排列
Minsum[0][i] = vis[i];
Minfun();//求出Min
++cur;
while (next_permutation(vis, vis + k)) {//得到全排列
for (int i = 0; i < k; i++)
Minsum[cur][i] = vis[i]; //把序列存入mark数组里面
Minfun();//判断是否最小值
cur++;
}
}
//输出函数
void output() {
for (int i = 0; i < k; i++)
printf("%c ", Minsum[ans][i] + 64);
printf("-> %d\n", Min);
}
//主函数
int main() {
int i, j;
char c;
int Tvis[27];
string str;
while (cin >> c) {
if (c == '#')
break;
memset(mark, 0, sizeof (mark));
memset(Tvis, 0, sizeof (Tvis));
memset(Minsum, 0, sizeof (Minsum));
i = c - 64;
vis[0] = i;
Tvis[i] = 1;
k = 1;
cin >> str;
//处理字符串
for (j = 0; j < str.size(); ++j) {
if (str[j] == ':') {
continue;
}
if (str[j] == ';') {
++j;
i = str[j] - 64;
if (isupper(str[j])) {
if (Tvis[str[j] - 64] == 0) {
Tvis[str[j] - 64] = 1;
vis[k] = str[j] - 64;
++k;
}
}
continue;
}
if (isupper(str[j])) {
if (Tvis[str[j] - 64] == 0) {
Tvis[str[j] - 64] = 1;
vis[k] = str[j] - 64;
++k;
}
}
mark[i][str[j] - 64] = 1;//标记为1,说明两个节点有连接
}
sort(vis, vis + k); //必须先对数组先排序
solve();
output();
}
}