目录
1,题目描述
Sample Input:
3
3 99 87 101
4 87 101 5 87
7 99 101 18 5 135 18 99
2
1 2
1 3
Sample Output:
50.0%
33.3%
题目大意
求两列数据的相似度。
Nc is the number of distinct common numbers shared by the two sets
Nc:两列数据(每个序列中需要先处理,使得元素不重复)中具有相同元素的数目;
Nt is the total number of distinct numbers in the two sets
Nt: 两列数据中所有不同元素的数目;
输出printf("%.1f%\n", (double)Nc * 100 / Nt);
2,思路
数据结构
- unordered_set<int> data[N + 1]:unordered_set为无序的set,速度快很多。
算法
- 将数据存放在data中,此时已经去重;
- 查询集合a,b时,只需遍历其中一个序列a,若元素同样存在于序列b,Nc++;
- Nt=a.size() + b.size() - Nc;
- printf("%.1f%\n", (double)Nc * 100 / Nt);
3,AC代码
#include<bits/stdc++.h>
using namespace std;
int main(){
#ifdef ONLINE_JUDGE
#else
freopen("1.txt", "r", stdin);
#endif // ONLINE_JUDGE
int N, M, K, x, id1, id2;
cin>>N;
unordered_set<int> data[N + 1];
for(int i = 1; i <= N; i++){
scanf("%d", &M);
for(int j = 0; j < M; j++){
scanf("%d", &x);
data[i].insert(x);
}
}
cin>>K;
for(int i = 0; i < K; i++){
scanf("%d %d", &id1, &id2);
int Nc = 0, Nt = 0;
// for(set<int>::iterator it = data[id1-1].begin(); it != data[id1-1].end(); it++){
for(auto it = data[id1].cbegin(); it != data[id1].cend(); it++){
if(data[id2].find(*it) != data[id2].cend())
Nc++;
}
Nt = data[id1].size() + data[id2].size() - Nc;
printf("%.1f%%\n", (double)Nc * 100 / Nt);
}
return 0;
}
4,解题过程
第一搏
将每一列数据保存在set集合里,选中两个set(比如a,b)后,调用函数,将集合a中的值依次加入b中,若b的size不增加,Nc++。最后Nk=b.size()。输出Nc/Nk;
注:对set不熟悉的同学可以看这里@周晓松的博客【关于C++中vector和set使用sort方法进行排序】
void getSim(set<int> a, set<int> b){
int Nc = 0, Nt = 0;
int tag = b.size();
for(set<int>::iterator it = a.begin(); it != a.end(); it++){
b.insert(*it);
if(tag == b.size())
Nc++;
tag = b.size();
}
Nt = b.size();
float ans = Nc * 100 / Nt;
printf("%.1f%\n", ans);
}
第二搏
第一次尝试,结果超时。。。然后就找到了这位大神的代码@日沉云起【pat甲级1063. Set Similarity (25)】,讲的很好!
其中涉及到了unrdered_set<int>:(头文件#include<bits/stdc++.h>)
遍历时用到了cbegin:@qq_42711815【C++迭代器中 cbegin,cend 与 begin,end 的区别】
cbegin和cend是C++11新标准引入的两个函数。
begin和end换回的具体类型由对象是否是常量来决定,如果是常量,begin和end换回const_iterator;如果不是常量,换回iterator;
cbegin和cend是不管是对象本身是不是常量,换回值都是const_iterator.
修改后,超时的问题解决了。。。然而
unordered_set<int> data[N];
.
.
.
for(int i = 0; i < K; i++){
scanf("%d %d", &id1, &id2);
int Nc = 0, Nt = 0;
// for(set<int>::iterator it = data[id1-1].begin(); it != data[id1-1].end(); it++){
for(auto it = data[id1-1].cbegin(); it != data[id1-1].cend(); it++){
if(data[id2-1].find(*it) != data[id2-1].cend())
Nc++;
}
Nt = data[id1-1].size() + data[id2-1].size() - Nc;
float ans = Nc * 100 / Nt;
printf("%.1f%\n", ans);
}
第三搏
终于发现,是输出的时候有问题。。。
注意一下两者的区别(这里还没有搞清楚为什么,恳请哪位大佬指点!)
printf("%.1f%\n", (double)Nc * 100 / Nt); 正确
printf("%.1f%\n", double(Nc * 100 / Nt)); 错误