zoj 2158 poj 1789 Truck History (Prim)

题目大意:

      高级货物运输公司ACM使用不同类型的卡车。有些卡车用来运蔬菜,有些用来运水果,还有一些用来运砖,等等。该公司对不同的卡车有自己的编码方法。卡车的编码为一个包含7个字符的字符串(每个位置上的字符都有特定的含义,但这一点对本题并不重要)。在ACM公司发展历史上的初期,只有一种卡车可供使用,只有一种卡车类型编码;后来又引进了新的一种卡车类型,新卡车的类型编码是从第一种卡车编码派生出来的;然后新的卡车类型编码又派生出其他卡车类型编码,等等。
       今天,ACM公司是如此的富有,可以让历史学家来研究公司的历史。历史学家试图弄明白的一件事情被称为派生方案,也就是,卡车的类型是如何派生的。他们将卡车类型编码的距离定义成卡车类型编码字符串中(7个位置上)不同字符的位置数目。比如,一个卡车编码是aaaaaaa,另一个卡车编码是babaaaaa,那么他们的距离值就是2。他们假定每种卡车类型都是由其他一种卡车类型派生出来的,当然,第一种卡车类型除外,它不是由任何其他一种类型派生的。派生方案的优劣值定义成:

其中,求和部分为派生方案中所有类型对(to, td)的距离,to为基类型,td为派生出来的类型。因为ACM公司卡车类型很多,历史学家很难判断这些类型编码之间派生关系。本题的目的是要求编写程序,实现:给定卡车类型的编码,求具有最高优劣值的派生方案。


题目太扯了,本题就是求:

最小值,而他就是最小生成树权值之和。这里用Prim思想解决的。

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const int INF = 10000010;
const int MAXN = 2010;
int n;
int lowcost[MAXN];
int Edge[MAXN][MAXN];
char codes[MAXN][10];

void Inite()
{
	int i, j, k;

	for(i = 0; i < n; ++i)
		cin>>codes[i];

	memset(Edge, 0, sizeof(Edge));
	for (i = 0; i < n; ++i)
	{
		for (j = i+1; j < n; ++j)
		{
			int dist = 0;
			for(k = 0; k < 7; ++k)
				if(codes[i][k] != codes[j][k])
					dist++;
			Edge[i][j] = Edge[j][i] = dist;
		}
	}
	memset(lowcost, 0, sizeof(lowcost));
}


void Prim()
{
	int i, j;
	int sum = 0;
	for(i = 0; i < n; ++i)
		lowcost[i] = Edge[0][i];
	lowcost[0] = -1;
	
	for (i = 1; i < n; ++i)
	{
		int MIN = INF, v = -1;
		for (j = 0; j < n; ++j)
		{
			if(lowcost[j] != -1 && MIN > lowcost[j])
			{
				v = j;
				MIN = lowcost[j];
			}
		}
		sum += MIN;
		lowcost[v] = -1;
		for (j = 0; j < n; ++j)
		{
			if(lowcost[j] != -1 && lowcost[j] > Edge[v][j])
				lowcost[j] = Edge[v][j];
		}
	}
	cout<<"The highest possible quality is 1/"<<sum<<"."<<endl;
}
int main()
{
	while (cin>>n && n)
	{
		Inite();
		Prim();
	}
	return 0;
}




你可能感兴趣的:(MST)