题目描述:
给定一张图,问如何顺序排列结点,能使排列中任意有边相连的两个节点之间的距离最大的值最小,如果有两个排列最大值相等,请输出字典序小的
分析:排列树+剪枝
在构造排列树的同时检查当前已经构成的序列中最大值是否小于最优质,如果大于剪掉即可
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int g[27][27];
int pm[27];
bool f[27];
int id;
int ans[27];
int maxx;
void permutation(int n,int *A,int cur)
{
if(cur==n)
{
int minx=1;
for(int i=0; i<n-1; ++i)
{
for(int j=i+1; j<n; ++j)
{
if(g[pm[A[i]]-'A'][pm[A[j]]-'A'])
if(minx<j-i)
minx=j-i;
}
}
if(minx<maxx)
{
maxx=minx;
for(int i=0; i<n; ++i)
ans[i]=A[i];
}
return;
}
else for(int i=0; i<n; i++)
{
int ok=1;
for(int j=0; j<cur; j++)
if(A[j]==i)
{
ok=0;
break;
}
if(ok)
{
A[cur]=i;
for(int j=0; j<cur; j++)
{
if(g[pm[i]-'A'][pm[A[j]]-'A'])
if(maxx<cur-j)
return;
}
permutation(n,A,cur+1);
}
}
}
int main()
{
char ch;
bool flag=false;
while(scanf("%c",&ch)==1&&ch!='#')
{
flag=true;
memset(f,false,sizeof(f));
memset(pm,0,sizeof(pm));
memset(g,0,sizeof(g));
maxx=0xfffffff;
id=0;
while(true)
{
if(!f[ch-'A'])
{
pm[id]=ch;
id++;
f[ch-'A']=true;
}
getchar();
char st;
while(scanf("%c",&st)==1&&st!=';'&&st!='\n')
{
if(!f[st-'A'])
{
pm[id]=st;
id++;
f[st-'A']=true;
}
g[ch-'A'][st-'A']=1;
g[st-'A'][ch-'A']=1;
}
if(st=='\n') break;
scanf("%c",&ch);
}
sort(pm,pm+id);
int a[27];
permutation(id,a,0);
for(int i=0; i<id; ++i)
printf("%c ",(char)pm[ans[i]]);
printf("-> %d",maxx);
printf("\n");
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/mengxingyuanlove/article/details/47164849