题目大意
给出一个图, 哪两个点相连, 问怎么排序使得相连点的间距最大值最小。
思路
很容易想到的思路就是dfs遍历解答树。但这样会超时,正确的做法是遍历的过程中进行剪枝
代码
// AC
#include <iostream>
#include <cstdio>
#include <cstring>
#include <climits>
#include <cmath>
#include <algorithm>
using namespace std;
bool road[30][30];
bool v[30];
int A[30];
int ans;
int dis;
int n;
int e[30];
void dfs(int cur) {
int dis = 0;
if (n == cur) {
for(int i = 0; i < n - 1; i++) {
for(int j = i + 1; j < n; j++) {
if (road[A[i]][A[j]]) {
dis = max(j - i, dis);
}
}
}
if (dis < ans) {
ans = dis;
for(int i = 0; i < n; i++) {
e[i] = A[i]; // e是用来保存最终结果的。
}
}
return;
}
for(int i = 0; i < 26; i++) {
if (v[i]) {
int ok = 1;
for(int j = 0; j < cur; j++) {
if (road[A[j]][i]) {
if (cur - j > ans) { // 剪枝, 如果间距大于以确定的最优解立刻甩掉这一条支路,这就是剪枝的含义。
ok = 0;
break;
}
}
}
if (ok) {
A[cur] = i;
v[i] = false;
dfs(cur+1);
v[i] = true;
}
}
}
}
int main()
{
// freopen("input.txt", "r", stdin);
char s[100];
while(scanf("%s", s) && s[0] != '#')
{
memset(road, false, sizeof(road));
memset(v, false, sizeof(v));
ans = INT_MAX;
dis = INT_MIN;
n = 0;
int flag = 1;
char u;
for(int i = 0; i < strlen(s); i++) {
if (flag) {
u = s[i];
if (!v[u-'A']) {
v[u-'A'] = true;
n++;
}
flag = 0;
}
else if (s[i] == ';') {
flag = 1;
}
else if (s[i] == ':') {
continue;
}
else {
road[u-'A'][s[i]-'A'] = road[s[i]-'A'][u-'A'] = true;
if (!v[s[i]-'A']) {
v[s[i]-'A'] = true;
n++;
}
}
}
dfs(0);
for(int i = 0; i < n; i++) {
printf("%c ", e[i] + 'A');
}
printf("-> %d\n", ans);
}
return 0;
}