题意:参考之前讲回溯法的最后一个问题。
思路:枚举全排列,考察每一种排列下的结果。 也可以进行剪枝优化,也是参见之前讲回溯法的部分。
这里我是用二维数组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