FZU - 2254 英语考试 (最小生成树)

题目链接:http://acm.fzu.edu.cn/problem.php?pid=2254点击打开链接



Problem 2254 英语考试

Accept: 188    Submit: 524
Time Limit: 1000 mSec    Memory Limit : 32768 KB

 Problem Description

在过三个礼拜,YellowStar有一场专业英语考试,因此它必须着手开始复习。

这天,YellowStar准备了n个需要背的单词,每个单词的长度均为m。

YellowSatr准备采用联想记忆法来背诵这n个单词:

1、如果YellowStar凭空背下一个新词T,需要消耗单词长度m的精力

2、如果YellowSatr之前已经背诵了一些单词,它可以选择其中一个单词Si,然后通过联想记忆的方法去背诵新词T,需要消耗的精力为hamming(Si, T) * w。

hamming(Si, T)指的是字符串Si与T的汉明距离,它表示两个等长字符串之间的汉明距离是两个字符串对应位置的不同字符的个数。

由于YellowStar还有大量繁重的行政工作,因此它想消耗最少的精力背诵下这n个单词,请问它最少需要消耗多少精力。

 Input

包含多组测试数据。

第一行为n, m, w。

接下来n个字符串,每个字符串长度为m,每个单词均为小写字母'a'-'z'组成。

1≤n≤1000

1≤m, w≤10

 Output

输出一个值表示答案。

 Sample Input

3 4 2abchabcdefgh

 Sample Output

10

 Hint

最优方案是:先凭空记下abcd和efgh消耗精力8,在通过abcd联想记忆去背诵abch,汉明距离为1,消耗为1 * w = 2,总消耗为10。


会建树就行

把每个单词看做城市

距离便是min(m,hamming(i,j)*w)

然后用最小生成树就能链接所有单词

最后加上第一个记忆单词需要的精力m

stl会超时

#include <queue>
#include <string>
#include <iostream>
#include <vector>
using namespace std;
int n,m,w;
char s[1111][11];
int pre[1111];
struct xjy
{
	int be;
	int en;
	int val;
	bool operator < (const xjy &r)const
	{
		return val>r.val;
	}
};
int findx(int x)
{
	int r=x;
	while(r!=pre[r])
		r=pre[r];
	int i=r,j;
	while(pre[i]!=r)
	{
		j=pre[i];
		pre[i]=r;
		i=j;
	}
	return r;
}
void join(int x,int y)
{
	int p1=findx(x);
	int p2=findx(y);
	if(p1!=p2)
	{
		pre[p2]=p1;
	}
}
int judge(int s1,int s2)
{
	int sum=0;
	for(int i=0;i<m;i++)
	{
		if(s[s1][i]!=s[s2][i])
			sum++;
	}
	return sum*w;
}
int main()
{
	while(scanf("%d%d%d",&n,&m,&w)!=EOF)
	{
		int ans=0;
		priority_queue <xjy > q;
		for(int i=0;i<n;i++)
		{
			pre[i]=i;
		}
		for(int i=0;i<n;i++)
		{
			scanf("%s",&s[i]);
		}
		for(int i=0;i<n;i++)
		{
			for(int j=i+1;j<n;j++)
			{
				xjy mid;
				mid.be=i;
				mid.en=j;
				mid.val=min(m,judge(i,j));
				q.push(mid);
			}
		}
		while(!q.empty())
		{
			xjy mid=q.top();
			q.pop();
			if(findx(mid.be)==findx(mid.en))
				continue;
			else 
			{
				ans+=mid.val;
				join(mid.be,mid.en);
			}
		}
		printf("%d\n",ans+m);
	}

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值