1063 Set Similarity (25分)
题目链接
1.题目分析:给定几个集合,如何计算出一对集合(两个)的相似性。即用两个集合的交集元素个数除以两个集合的并集元素个数。
2.思路分析:
方法1:用set集合数组分别存放每一个集合,然后对于待查询的a,b集合求它们的交集元素个数和并集元素个数。开始没有关注时间复杂度,在计算交集和并集的时候采用将两个集合的元素存放在新的set集合里面,然后得到并集元素个数。然后用原来两个集合的元素总和减去现在的并集元素个数就是交集元素个数了。这样的算法在小规模数据还可行,但是不能符合本题要求所以超时!!
代码:`
#include <bits/stdc++.h>
using namespace std;
//下面这个算法超时
int main()
{
int n;
double result=0.0;
scanf("%d",&n);
set<int> st[n];//set二位数组,用来存放初次集合
for(int i=0; i<n; i++) //第i个集合
{
int m=0,x;
scanf("%d",&m);//集合中包含的元素个数
for(int j=0; j<m; j++)
{
scanf("%d",&x);
st[i].insert(x);
}
}
int k,a,b,nt=0,nc=0;
scanf("%d",&k);//要求查询的组数
for(int i=0; i<k; i++)
{
scanf("%d%d",&a,&b);
result=0;
int nt=st[a-1].size()+st[b-1].size();//未合并前两个集合的长度之和
set<int> st2;
for(set<int>::iterator it=st[a-1].begin(); it!=st[a-1].end(); it++)
{
st2.insert(*it);
}
for(set<int>::iterator it=st[b-1].begin(); it!=st[b-1].end(); it++)
{
st2.insert(*it);
}
int nc=0;
nc=nt-st2.size();//nc
result=(double)nc/st2.size();
printf("%.1f%%\n",result*100);
}
return 0;
}
方法2:参考算法笔记算法,用遍历集合a,然后在集合b中找相应的元素。如果在b’中找到该元素,则交集个数加一;如果没有找到则并集个数加一(并集初始值为b的元素个数和)。这样就可以找出需要的两个结果。然后格式化输出即可。
~~注意%号输出时,必须%%才可正常输出%哦。
~~
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int N=55;
set<int> st[N];
void compare(int x,int y){
int tonum=st[y].size(),samenum=0;
//遍历集合st[x];
for(set<int>::iterator it=st[x].begin();it!=st[x].end();it++){
if(st[y].find(*it)!=st[y].end()) //在y集合中找到该元素
samenum++;//交集数+1
else tonum++;//并集数+1
}
printf("%.1f%%\n",samenum*100.0/tonum);
}
int main(){
int n,k,x,q,a,b;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&k);
for(int j=0;j<k;j++){
scanf("%d",&x);
st[i].insert(x);//添加x到st[i]中
}
}
scanf("%d",&q);
for(int i=0;i<q;i++){
scanf("%d%d",&a,&b);
compare(a,b);
}
return 0;
}