POJ1789 Truck History

用一个7位的string代表一个编号,两个编号之间的距离代表这两个编号之间不同字母的个数。一个编号只能由另一个编号“衍生”出来,代价是这两个编号之间相应的距离,现在要找出一个“衍生”方案,使得总代价最小。
N<=2000;
´4个编号:
´aaaaaaa
´baaaaaa
´abaaaaa
´aabaaaa

    后三个均由第一个衍生可得到最小距离和1+1+1=3.


1. 所有的“衍生方案”可表示为一幅图。
    求一种“衍生方案”,实质上是去构造一棵树。
    树的顶点代表编号,树的边权代表不同编号之间的衍生代价。
    因为需要衍生出所有的方案而使总代价最小,所以要求最小生成树。

2.这是一幅稠密图,边数很多,所以选用邻接矩阵存储图、Prim算法实现最小生成树更优。


#include<iostream>
#include<cstdio>
#include<cstring>
#define inf 999999
using namespace std;

int n,dis[2001][2001];
char s[2001][8];

int weight(int a, int b) {  //返回两个编号的衍生代价 
	int sum = 0;
	for (int i=0; i<7; i++)
		if (s[a][i] != s[b][i]) sum++;
	return sum;
}

int prim() {
	bool book[2001];  //book数组表示点是否被选进了树中 
	int ans = 0, lowd[2001], Min, k, s = 1;
	
	memset(lowd,inf,sizeof(lowd));
	memset(book,false,sizeof(book));
	book[s] = true;
	
	for (int i=1; i<n; i++) {
		Min = inf;
		for (int j=2; j<=n; j++) {
			if (!book[j] && lowd[j] > dis[s][j])
				lowd[j] = dis[s][j];
			if (!book[j] && Min > lowd[j]) {
				Min = lowd[j];
				k = j;
			}
		}
		book[k] = true;
		s = k;  //s点不断更新 
		ans += Min;
	}
	return ans;
}

int main() 
{
	while (scanf("%d",&n) == 1 && n) {
		for (int i=1; i<=n; i++) scanf("%s",s[i]);
		for (int i=1; i<=n-1; i++)  //注意这里i和j的循环范围,避免重复赋值 
			for (int j=i+1; j<=n; j++)
				dis[i][j] = dis[j][i] = weight(i,j);
				
		printf("The highest possible quality is 1/%d.\n",prim());
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值