题目链接如下:
这道题我写得太罗嗦了,其实每次dfs深一层的时候,只要算最后加的这个点跟当前已确定的点中、从前往后看最早跟它联结的点之间的距离,大于等于minWidth就可以剪枝。
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <cmath>
// #define debug
std::string str, s, result;
char node, ch;
char ans[10];
int minWidth, sz;
std::vector<char> vec[26];
int exist[26];
int calWidth(){
int len = 1;
int loc[26];
for (int i = 0; i < sz; ++i){
loc[ans[i] - 'A'] = i;
}
for (int i = 0; i < 26; ++i){
for (int j = 0; j < vec[i].size(); ++j){
int temp = std::abs(loc[i] - loc[vec[i][j] - 'A']);
if (temp >= minWidth){
return 10;
}
len = std::max(len, temp);
}
}
return len;
}
void dfs(int k){
if (k == sz){
int temp = calWidth();
if (temp < minWidth){
minWidth = temp;
result = ans;
}
return;
}
for (int i = 0; i < sz; ++i){
int flag = 1;
for (int j = 0; j < k; ++j){
if (ans[j] == s[i]){
flag = 0;
break;
}
}
if (flag){
ans[k] = s[i];
dfs(k + 1);
}
}
}
int main(){
#ifdef debug
freopen("0.txt", "r", stdin);
freopen("1.txt", "w", stdout);
#endif
while (getline(std::cin, str) && str != "#"){
for (int i = 0; i < 26; ++i){
exist[i] = 0;
vec[i].clear();
}
std::stringstream ss(str);
while (ss >> node){
exist[node - 'A'] = 1;
ss >> ch;
while (ss >> ch){
if (ch == ';'){
break;
}
exist[ch - 'A'] = 1;
vec[node - 'A'].push_back(ch);
}
}
minWidth = 10;
s.clear();
for (int i = 0; i < 26; ++i){
if (exist[i]){
s.push_back(i + 'A');
}
}
sz = s.size();
dfs(0);
for (int i = 0; i < sz; ++i){
printf("%c ", result[i]);
}
printf("-> %d\n", minWidth);
}
#ifdef debug
fclose(stdin);
fclose(stdout);
#endif
return 0;
}
我写得很麻烦,但我懒得再改了。
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <cmath>
// #define debug
std::string str, s, result;
char node, ch;
char ans[10];
int minWidth, sz;
std::vector<char> vec[26];
int exist[26];
int calWidth(){
int len = 1;
int loc[26];
for (int i = 0; i < sz; ++i){
loc[ans[i] - 'A'] = i;
}
for (int i = 0; i < 26; ++i){
for (int j = 0; j < vec[i].size(); ++j){
int temp = std::abs(loc[i] - loc[vec[i][j] - 'A']);
if (temp >= minWidth){
return 10;
}
len = std::max(len, temp);
}
}
return len;
}
void dfs(int k){
if (k == sz){
int temp = calWidth();
if (temp < minWidth){
minWidth = temp;
result = ans;
}
return;
}
for (int i = 0; i < sz; ++i){
int flag = 1;
for (int j = 0; j < k; ++j){
if (ans[j] == s[i]){
flag = 0;
break;
}
}
if (flag){
ans[k] = s[i];
int loc[26];
for (int j = 0; j < 26; ++j){
loc[j] = -1;
}
for (int j = 0; j <= k; ++j){
loc[ans[j] - 'A'] = j;
}
int ok = 1;
for (int j = 0; j < 26; ++j){
for (int l = 0; l < vec[j].size(); ++l){
if (loc[j] != -1 && loc[vec[j][l] - 'A'] != -1 && std::abs(loc[j] - loc[vec[j][l] - 'A']) >= minWidth){
ok = 0;
j = 26;
break;
}
}
}
if (ok){
dfs(k + 1);
}
}
}
}
int main(){
#ifdef debug
freopen("0.txt", "r", stdin);
freopen("1.txt", "w", stdout);
#endif
while (getline(std::cin, str) && str != "#"){
for (int i = 0; i < 26; ++i){
exist[i] = 0;
vec[i].clear();
}
std::stringstream ss(str);
while (ss >> node){
exist[node - 'A'] = 1;
ss >> ch;
while (ss >> ch){
if (ch == ';'){
break;
}
exist[ch - 'A'] = 1;
vec[node - 'A'].push_back(ch);
}
}
minWidth = 10;
s.clear();
for (int i = 0; i < 26; ++i){
if (exist[i]){
s.push_back(i + 'A');
}
}
sz = s.size();
dfs(0);
for (int i = 0; i < sz; ++i){
printf("%c ", result[i]);
}
printf("-> %d\n", minWidth);
}
#ifdef debug
fclose(stdin);
fclose(stdout);
#endif
return 0;
}