题意:参考之前讲回溯法的最后一个问题。
思路:枚举全排列,考察每一种排列下的结果。 也可以进行剪枝优化,也是参见之前讲回溯法的部分。
这里我是用二维数组g来存边关系,但顶点还是单独保存在一个数组里,然后排序,然后求排列。
这题居然交了9次,1CE1TLE1AC6WA,CE的原因是没有包含cstring,在本地没包含可以。。。TLE原因是没有注释掉freopen。WA的原因之前一直以为是输出有问题,因为找了很多数据都通过了,以及题目说最多8个结点,但是图还是要开26X26啊。。。一次一次修改,虽然WA,但程序跑的时间变长些了,然后在第88行,i 的初始值开始写的是cur+1,改为0的时候,WA了,但是时间也变长了,由此才发现问题。就是结点在图矩阵中的下标和结点数组nd中的下标搞混了。找的数据都通过的原因,可能是数据构造的不好,都是顺序的,只有一个AZ的,其他好像都是顺序的,可能没有凸显下标混淆的问题。。。(之前找不到问题,甚至猜是不是输入中含空格。。。应该不是,因为别人用scanf都可以AC)
综上,此题应注意的地方:一、图数组至少开26X26,二、顶点在两类数组中的下标需要注意下。
Code:
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> void print(); int compute(int cur); void solve(); using namespace std; //int g[8][8]; int g[26][26]; int nd[8]; int n; int bestwd; int bestnd[8]; int main() { //freopen("140.in","r",stdin); //freopen("140.out","w",stdout); char c; int flag=0; n=0; bestwd=1000; memset(g,0,sizeof(g)); int node; int adjnd; //int num=0; while((c=getchar())!='#') { if(c=='\n') { sort(nd,nd+n); solve(); //if(num++) printf("\n"); print(); flag=0; n=0; bestwd=1000; memset(g,0,sizeof(g)); } else if(c==':') { flag=1; } else if(c==';') { flag=0; } else if(isalpha(c)) { if(flag==0) node=c-'A'; else { adjnd=c-'A'; g[node][adjnd]=1; g[adjnd][node]=1;} int i=0; for(;i<n;++i) if(nd[i]==c-'A') break; if(i>=n) nd[n++]=c-'A'; } } return 0; } void solve() { do { int wd=0;//该排列下,图的带宽 for(int i=0;i<n;++i)//当前元素在nd中的位置 { int ndwd=compute(i); wd=ndwd>wd?ndwd:wd; } if(wd<bestwd) { memcpy(bestnd,nd,sizeof(bestnd)); bestwd=wd; } }while(next_permutation(nd,nd+n)); } int compute(int cur) { int ndwd=0; int k=nd[cur];//当前元素在g中的位置 for(int i=k+1;i<26;++i)//这里是找存在的元素,是<26,不是<n { if(g[k][i]) { int j=0;//元素i在nd中的位置 for(;j<n;++j) if(nd[j]==i) break; int tempwd=j-cur>=0?j-cur:cur-j; ndwd=tempwd>ndwd?tempwd:ndwd; } } return ndwd; } void print() { for(int i=0;i<n;++i) printf("%c ",bestnd[i]+'A'); printf("-> %d\n",bestwd); }
//错误代码,有些细节写错。修改成了版本2 //留着,和AC的代码对比。 #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> void print(); int compute(int cur); void solve(); using namespace std; //int g[8][8]; int g[26][26]; int nd[8]; int n; int bestwd; int bestnd[8]; int main() { freopen("140.in","r",stdin); freopen("140.out","w",stdout); char c; int flag=0; n=0; bestwd=1000; memset(g,0,sizeof(g)); int node; int adjnd; //int num=0; while((c=getchar())!='#') { if(c=='\n') { sort(nd,nd+n); solve(); //if(num++) printf("\n"); print(); flag=0; n=0; bestwd=1000; memset(g,0,sizeof(g)); } else if(c==':') { flag=1; } else if(c==';') { flag=0; } else if(isalpha(c)) { if(flag==0) node=c-'A'; else { adjnd=c-'A'; g[node][adjnd]=1; g[adjnd][node]=1;} int i=0; for(;i<n;++i) if(nd[i]==c-'A') break; if(i>=n) nd[n++]=c-'A'; } } return 0; } void solve() { do { int wd=0;//该排列下,图的带宽 for(int i=0;i<n;++i) { int ndwd=compute(i); wd=ndwd>wd?ndwd:wd; } if(wd<bestwd) { memcpy(bestnd,nd,sizeof(bestnd)); bestwd=wd; } }while(next_permutation(nd,nd+n)); } int compute(int cur) { int ndwd=0; int k=0;//当前元素在nd中的位置 for(;k<n;++k) if(nd[k]==cur) break; for(int i=0;i<26;++i)//这里是找存在的元素,是<26,不是<n { if(g[cur][i]) { int j=0;//元素i在nd中的位置 for(;j<n;++j) if(nd[j]==i) break; int tempwd=j-k>=0?j-k:k-j; ndwd=tempwd>ndwd?tempwd:ndwd; } } return ndwd; } void print() { for(int i=0;i<n;++i) printf("%c ",bestnd[i]+'A'); printf("-> %d\n",bestwd); }
原文地址:http://blog.csdn.net/buxizhizhou530/article/details/44119007