题意:找出所有的排列中带宽的最小值,而每个排列的带宽是这个排列中最大的距离
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int map[30][30],n=0,m;
int a[10],vis[10],check[30];
int p[10],ans[10],Min;
int dfs(int cur)
{
if (cur == m)
{
int k = 0 ;
for (int i = 0; i < m-1; i++) //求带宽的最大值,枚举每一种可能
{
for (int j = i; j < m; j++)
{
if(map[a[p[i]]][a[p[j]]])
{
int t = i-j>0?i-j:j-i;
if (t > k)
k = t ;
}
}
}
if (k < Min) // 找出所以排列的最小值
{
Min = k ;
for (int i = 0; i < m; i++)
ans[i] = a[p[i]];
}
}
for (int i = 0; i < m; i++) // 排列树的生成
{
if (!vis[i])
{
vis[i] = 1;
p[cur] = i ; //依次储存下标
dfs(cur+1);
p[cur] = 0 ;
vis[i] = 0 ;
}
}
}
int main()
{
char ch,t;
memset(map,0,sizeof(map));
memset(vis,0,sizeof(vis));
memset(check,0,sizeof(check));
while (1)
{
scanf("%c",&ch);
if (ch == '#')
break;
else
{
t = ch ;
getchar();
while (1)
{
scanf("%c",&ch);
if (ch == ';' || ch =='\n')
break;
map[t-'A'][ch-'A']=map[ch-'A'][t-'A'] = 1;
check[t-'A'] = check[ch-'A'] = 1 ; //并不是每个字母都有用到
}
}
if (ch == '\n')
{
m = 0;
for (int i = 0; i < 26; i++)
{
if (check[i])
a[m++] = i; //储存需要的字母,便于全排列
}
Min = m;
dfs(0);
for (int i = 0; i < m; i++)
printf("%c ",ans[i]+'A');
printf("-> %d\n",Min);
memset(map,0,sizeof(map));
memset(vis,0,sizeof(vis));
memset(check,0,sizeof(check));
n=0;
}
}
return 0;
}