poj 1789 卡车编号

题意:求一种编号方式使得所有不同类型卡车权值最小

 

题意大概是这样的:用一个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;
}                                              



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值