L2-005. 集合相似度

来源:互联网 发布:软件设计师大纲 编辑:程序博客网 时间:2024/05/22 12:55

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位的百分比数字。

输入样例:
33 99 87 1014 87 101 5 877 99 101 18 5 135 18 9921 21 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;}




原创粉丝点击