//uva140 AC10ms
/*刘叔书里说起了剪枝,就想试一下,昨晚一直WA,想看刘叔的代码发现他用的是直接枚举,讲道理我觉得剪枝对条件的筛选也需要时间,不一定快,下面是递归和加入
剪枝的AC代码,刚才跑了一下变成20ms,不管了吃饭去*/
#include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <algorithm> using namespace std; int A[8], g[8][8], num[8]; int ans[8]; int vis[8]; int ch2int[256]; char int2ch[8]; int _min; int n; void dfs( int cur) { if (cur == n) {//新排列 int max = 0; for(int i=0;i<n;i++) for (int j = 0;j < n;j++) { if (i!=j&&g[A[i]][A[j]] && fabs(i - j) > max)max = (int)fabs(i - j); } if (max < _min) { _min = max; memcpy(ans, A, sizeof(A)); } return; } for(int i=0;i<n;i++) if (!vis[i]) { A[cur] = i; vis[i] = 1; int ok = 1;//假设进行dfs for (int i = 0;i <= cur;i++) { int count = 0, max = 0; for(int j=0;j<=cur;j++) if (i!= j&&g[A[i]][A[j]]) { count++; if (fabs(i - j) > max)max = (int)fabs(i - j); } if(max>_min || (num[i] - count > 0 && num[i] - count + cur - i > _min)//没有这个剪枝20ms ) { ok = 0;break; } } if (ok)dfs( cur + 1); vis[i] = 0; } } char s[205]; int main(void) { while (scanf("%s",s)==1 && s[0] != '#') { memset(vis, 0, sizeof(vis)); memset(g, 0, sizeof(g)); memset(num, 0, sizeof(num)); _min = 10; //printf("%d", 'A'); //fgets(s, 100, stdin); int len = strlen(s); n = 0; for (char ch = 'A';ch <= 'Z';ch++) if (strchr(s, ch) != NULL) { ch2int[(int)ch] = n; int2ch[n] = ch; n++; } int pre; for (int i = 0;i < len;i++) { char c = s[i]; //int pre; if (c <= 'Z'&&c >= 'A') { if (s[i + 1] == ':')pre = ch2int[(int)c]; else { //printf("debug:%d", pre); int ne = ch2int[(int)c]; g[pre][ne] = g[ne][pre] = 1; num[pre]++; /*这里如果把下一行"num[ne]++;"注释掉,然后没有下面的num[i]除以2,说实话我不知道为什么这样改就WA,这样好像num[i]也能保证小于等于i的相邻结点数?如若看 过代码知道鄙人错误欢迎指出*/ num[ne]++; } } } //输入有点迷,看起来像是有向表,解析给我的感觉是无向表,无论如何,除以2后num[i]总是小于等于i的相邻节点数 for (int i = 0;i < n;i++)num[i] /= 2; dfs(0); for (int i = 0; i < n; i++) { printf("%c ", int2ch[ans[i]]); } printf("-> %d ", _min); } return 0; }