题意大概是这样的:用一个7位的string代表一个编号,两个编号之间的distance代表这两个编号之间不同字母的个数。一个编号只能由另一个编号“衍生”出来,代价是这两个编号之间相应的distance,现在要找出一个“衍生”方案,使得总代价最小,也就是distance之和最小。
例如有如下4个编号:
aaaaaaa
baaaaaa
abaaaaa
aabaaaa
显然的,第二,第三和第四编号分别从第一编号衍生出来的代价最小,因为第二,第三和第四编号分别与第一编号只有一个字母是不同的,相应的distance都是1,加起来是3。也就是最小代价为3。
问题可以转化为最小代价生成树的问题。因为每两个结点之间都有路径,所以是完全图。
#include <iostream>
#include <stdio.h>using namespace std;
#define MAXV 2001
#define INF 999999999
/*
prim算法:从第一个点出发,寻找最近的距离
每一次都寻找离这个堆最近距离的点,寻找到
最后一个点。
*/
int n;
char s[MAXV][8];
int map[MAXV][MAXV];
int d[MAXV];
bool vis[MAXV];
void prim()
{
int i,j,v,tmp;
for(i=0;i<n;i++)//第一个点距离所有点的距离
{
vis[i]=0;
d[i]=map[0][i];
}
for(i=1;i<=n;i++)
{
tmp=INF;
for(j=0;j<n;j++)//找出距离最小的一个点出来
{
if(!vis[j]&&tmp>d[j])
{
tmp=d[j];
v=j;
}
}
vis[v]=1;
for(j=0;j<n;j++)//进行距离的调整,可能对加入的点距离更近
{
if(!vis[j]&&d[j]>map[v][j])
{
d[j]=map[v][j];
}
} }
for(d[0]=0,i=1;i<n;i++)d[0]+=d[i];
printf("The highest possible quality is 1/%d.\n",d[0]);
}
int main(){
int i,j,k,num;
while(scanf("%d",&n) && n){
for(i=0;i<n;i++){ //这里map可以不用初始化,因为每个两个点都有值
scanf("%s",s[i]);
for(j=0;j<i;j++){
num=0;
for(k=0;k<7;k++)
if(s[i][k]!=s[j][k])
num++;
map[i][j]=map[j][i]=num;
}
}
prim();
}
return 0;
}