题目链接在这里
题目大意:
有n辆卡车,每个卡车有一个编号,编号由七个字母组成。卡车之间的距离是两车字母不同的数量。让你选择一种方式将卡车连起来,使他们的距离总和最小。
思路分析:
先暴力求出每个卡车之间的距离,然后建立最小生成树就好。
代码如下:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#define rep(i, x) for(int i = 0; i < x; ++i)
#define clr(x) memset(x, 0, sizeof(x))
using namespace std;
const int MaxN = 2005;
struct Edge{
int x, y, val;
bool operator < (const Edge &e) const{
return val > e.val;
}
};
int n;
char str[MaxN][8];
int r[MaxN], par[MaxN];
int getDis(char *p, char *q){
int val = 0;
rep(i, 7){
if(*p != *q){
++val;
}
++p;
++q;
}
return val;
}
void init(){
clr(r);
rep(i, MaxN) par[i] = i;
}
int Find(int x){
if(x == par[x]) return x;
return par[x] = Find(par[x]);
}
void unite(int x, int y){
x = Find(x);
y = Find(y);
if(x == y) return ;
if(r[x] < r[y]) par[x] = y;
else{
par[y] = x;
if(r[x] == r[y]) ++r[x];
}
}
bool check(int x, int y){
return Find(x) == Find(y);
}
void solve(){
priority_queue<Edge> que;
rep(i, n){
rep(j, i){
int val = getDis(str[i], str[j]);
//printf("x:%d, y:%d, val:%d\n", i, j, val);
que.push(Edge{i, j, val});
}
}
int ans = 0;
while(--n){
Edge e = que.top();
que.pop();
if(check(e.x, e.y)){
++n;
continue;
}
ans += e.val;
unite(e.x, e.y);
}
printf("The highest possible quality is 1/%d.\n", ans);
}
int main(){
while(~scanf("%d", &n) && n){
init();
rep(i, n){
scanf("%s", str[i]);
}
solve();
}
}