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;
}