题意:求一种编号方式使得所有不同类型卡车权值最小
题意大概是这样的:用一个7位的string代表一个编号,两个编号之间的distance代表这两个编号之间不同字母的个数。一个编号只能由另一个编号“衍生”出来,代价是这两个编号之间相应的distance,现在要找出一个“衍生”方案,使得总代价最小,也就是distance之和最小。
例如有如下4个编号:
aaaaaaa
baaaaaa
abaaaaa
aabaaaa
显然的,第二,第三和第四编号分别从第一编号衍生出来的代价最小,因为第二,第三和第四编号分别与第一编号只有一个字母是不同的,相应的distance都是1,加起来是3。也就是最小代价为3。
问题可以转化为最小代价生成树的问题。因为每两个结点之间都有路径,所以是完全图。
参考:http://blog.csdn.net/lyy289065406/article/details/6645974
#include <iostream>
#include <sstream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <cctype>
#include <algorithm>
#include <cmath>
#include <deque>
#include <queue>
#include <map>
#include <queue>
#include <list>
#include <iomanip>
using namespace std;
///
///
const int INF = 20000000;
#define maxn 2012
#define max(a,b)(a>b?a:b)
///
int n;
char str[maxn][8];
int dist[maxn][maxn];
int weight(int i,int j)
{
int w = 0;
int k;
for (k = 0; k < 7; k++)
{
if (str[i][k] != str[j][k])
w++;
}
return w;
}
int prim()
{
int i, j;
int s = 1;//源点
int m = 1;//最小生成树顶点个数
bool u[maxn];//判定是否属于最小生成树
int prim_w = 0; //最小生成树的总权值
int min_w; //每个新源点到其它点的最短路
int flag_point;
int low_dis[maxn]; //各个源点到其它点的最短路
// memset(low_dis, INF, sizeof(low_dis));
for (i = 1; i <= n; i++)
{
low_dis[i] = INF;
}
memset(u, false, sizeof(u));
u[s] = true;
while (1)
{
if (m == n)
break;
min_w = INF;
for (j = 2; j <= n; j++)
{
//更新操作
if (!u[j] && low_dis[j] > dist[s][j])
low_dis[j] = dist[s][j];
if (!u[j] && min_w > low_dis[j])
{
min_w = low_dis[j];
flag_point = j;
}
}
s = flag_point;//新的源点
u[s] = true;
prim_w += min_w;
m++;
}
return prim_w;
}
int main()
{
freopen("F:\\input.txt","r",stdin );
///
int i, j;
while (1)
{
cin >> n;
if (n == 0)
break;
for (i = 1; i <= n; i++)
cin >> str[i];
//建立邻接图
for (i = 1; i <= n - 1; i++)
{
for (j = i + 1; j <= n; j++)
{
dist[i][j] = dist[j][i] = weight(i, j);
}
}
//计算
cout<<"The highest possible quality is 1/"<< prim() <<'.'<<endl;
}
///
return 0;
}