题目链接
题目大意:
给出一个n(n≤8)个结点的图G和一个结点的排列,定义结点i的带宽b(i)为i和相邻结点 在排列中的最远距离,而所有b(i)的最大值就是整个图的带宽。给定图G,求出让带宽最小 的结点排列。
分析:
可以记录下目前已经找到的最小带宽k。如果发现已经有某两个结点的距离大于或等 于k,再怎么扩展也不可能比当前解更优,应当强制把它“剪”掉。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 50;
int matrix[maxn][maxn];
int min_arr[maxn];
int arr[maxn];
bool vis[maxn];
int n, ans;
void dfs(int cur) {
int dis = 0;
if(cur==n) {
for(int i = 0; i < n-1; i++) {
for(int j = i+1; j < n; j++) {
if(matrix[arr[i]][arr[j]]) {
if((j-i)>dis) dis = (j-i);
}
}
}
if(ans>dis) {
ans = dis;
for(int i = 0; i < n; i++)
min_arr[i] = arr[i];
}
return;
}
else {
for(int i = 0; i < 26; i++) {
if(vis[i]) {
bool ok = true;
for(int j = 0; j < cur; j++) {
if(matrix[i][arr[j]]) {
//当前已有两个结点的距离大于ans,对解答树剪枝
if(cur-j>ans) {
ok = false;
break;
}
}
}
if(ok) {
vis[i] = false;
arr[cur] = i;
dfs(cur+1);
vis[i] = true;//辅助数组要恢复
}
}
}
}
}
int main() {
freopen("i.txt","r",stdin);
freopen("o.txt","w",stdout);
string str,s;
while(cin >> str && str!="#") {
memset(vis, false, sizeof(vis));
memset(min_arr, 0, sizeof(min_arr));
memset(matrix, 0, sizeof(matrix));
n = 0, ans = INT_MAX;
for(int i = 0; i < (int)str.length(); i++) {
if(isalpha(str[i]) && !vis[str[i]-'A']) {
arr[n++] = str[i];
vis[str[i]-'A'] = true;
}
}
for(int i = 0; i < (int)str.length(); i++) {
if(str[i]==';') str[i] = ' ';
}
stringstream ss(str);
while(ss>>s) {
for(int i = 2; i < (int)s.length(); i++)
matrix[s[0]-'A'][s[i]-'A'] = matrix[s[i]-'A'][s[0]-'A'] = 1;
}
dfs(0);
for(int i = 0; i < n; i++)
cout << char(min_arr[i]+'A') <<" ";
cout << "-> " << ans << endl;
}
return 0;
}
第一次没有剪枝做的,一直wa但没有判TLE不知道为啥。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 200;
vector<int> vec[maxn];
int min_arr[maxn];
int arr[maxn];
bool vis[maxn];
int n, mmin;
int Judge(int n) {
int m = 0;
for(int i = 0; i < n; i++) {
auto it1 = find(arr, arr+n, i);
for(int j = 0; j < (int)vec[i].size(); j++) {
auto it2 = find(arr, arr+n, vec[i][j]);
if(abs(it2-it1)>m) m = abs(it2-it1);
}
}
return m;
}
int main() {
string str,s;
while(cin >> str && str!="#") {
memset(vis, false, sizeof(vis));
memset(min_arr, 0, sizeof(min_arr));
mmin = 0;
for(int i = 0; i < maxn; i++) vec[i].clear();
n = 0;
for(int i = 0; i < (int)str.length(); i++) {
if(isalpha(str[i]) && !vis[str[i]-'A']) {
arr[n++] = str[i]-'A';
vis[str[i]-'A'] = true;
}
}
for(int i = 0; i < (int)str.length(); i++) {
if(str[i]==';') str[i] = ' ';
}
stringstream ss(str);
while(ss>>s) {
for(int i = 2; i < (int)s.length(); i++)
vec[s[0]-'A'].push_back(s[i]-'A');
}
sort(arr, arr+n);
mmin = maxn*maxn;
do{
if(mmin>Judge(n)) {
mmin = Judge(n);
for(int i = 0; i < n; i++)
min_arr[i] = arr[i];
}
}while(next_permutation(arr, arr+n));
for(int i = 0; i < n; i++)
cout << char(min_arr[i]+'A') <<" ";
cout << "-> " << mmin << endl;
}
return 0;
}