L2-005. 集合相似度

L2-005. 集合相似度

时间限制
400 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
陈越

给定两个整数集合,它们的相似度定义为:Nc/Nt*100%。其中Nc是两个集合都有的不相等整数的个数,Nt是两个集合一共有的不相等整数的个数。你的任务就是计算任意一对给定集合的相似度。

输入格式:

输入第一行给出一个正整数N(<=50),是集合的个数。随后N行,每行对应一个集合。每个集合首先给出一个正整数M(<=104),是集合中元素的个数;然后跟M个[0, 109]区间内的整数。

之后一行给出一个正整数K(<=2000),随后K行,每行对应一对需要计算相似度的集合的编号(集合从1到N编号)。数字间以空格分隔。

输出格式:

对每一对需要计算的集合,在一行中输出它们的相似度,为保留小数点后2位的百分比数字。

输入样例:
3
3 99 87 101
4 87 101 5 87
7 99 101 18 5 135 18 99
2
1 2
1 3
输出样例:
50.00%
33.33%
思路分析:

利用set处理集合,自动删掉重复出现过的元素。

注意:

本题最后一组测试数据量较大,为了减少运行时间,一方面可以加一个二维数组保存求过的集合相似度,避免重复运算,另一方面在就总的不同整数个数时,不要遍历两个set并插入一个新的set中,可以直接新建一个set让它等于seq[v1],然后只需遍历另一个set并插入,可以减少一半的运算量。(不要直接往seq[v1]中插,因为后边还要再用到,破坏好会影响后边的计算)。

题解:

#include <cstdio>
#include <set>
using namespace std;
const int MAX = 51;
int n, m, k;
set<int> seq[MAX];
double g[MAX][MAX] = {0};

int main(){
	scanf("%d", &n);
	for(int i = 1; i <= n; i++){
		scanf("%d", &m);
		while(m--){
			int v;
			scanf("%d", &v);
			seq[i].insert(v);
		}
	}
	scanf("%d", &k);
	while(k--){
		int v1, v2, nc = 0, nt = 0;
		scanf("%d %d", &v1, &v2);
		if(g[v1][v2] == 0){
			set<int> ans = seq[v2];
			set<int>::iterator it;
			for(it = seq[v1].begin(); it != seq[v1].end(); it++){
				ans.insert(*it);
			}
			nt = ans.size();
			nc = seq[v1].size()+seq[v2].size()-ans.size();
			g[v1][v2] = g[v2][v1] = (double)nc/(double)nt*100;
		}
		printf("%.2f%%\n", g[v1][v2]);
	}
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值