PAT甲级 1063 Set Similarity (25 分)
一、暴力解法(21分)
暴力解法就是创建N个集合set,因为集合保证了元素不重复,依次往每个集合中insert数字即可。统计相同元素和所有不同元素个数时可以用map完成,即map中某个元素出现次数为2,那么这是公共元素;map中所有元素个数为不同数字个数。这样做会导致最后一个测试点超时。
程序如下:
#include <bits/stdc++.h>
using namespace std;
set<int> s[50];
void solve(set<int> &s1, set<int> &s2)
{
map<int, int> m;
set<int>:: iterator it1, it2;
for(it1=s1.begin(); it1!=s1.end(); it1++)
{
m[*it1]++;
}
for(it2=s2.begin(); it2!=s2.end(); it2++)
{
m[*it2]++;
}
int Nc = 0, Nt = 0;
map<int, int>:: iterator it;
for(it=m.begin(); it!=m.end(); it++)
{
Nt ++;
if(it->second==2) Nc ++; // 表示这个数在两个集合中都出现过
}
float res = (float)(Nc*100)/(float)Nt;
printf("%.1f%%\n", res);
return;
}
int main(int argc, char const *argv[])
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; ++i)
{
int num;
scanf("%d", &num);
int temp;
for (int j = 0; j < num; ++j)
{
scanf("%d", &temp);
s[i].insert(temp);
}
}
int k;
scanf("%d", &k);
int a, b;
for (int i = 0; i < k; ++i)
{
scanf("%d%d", &a, &b);
solve(s[a-1], s[b-1]);
}
return 0;
}
二、就在集合内查找是否包含另一个集合内元素
我感觉这种常规暴力会超时,没想到set的find函数优化很好,竟然可以过!震惊!!!就直接对a集合内元素遍历,查找b集合内是否包含此元素即可。如果不包含,则返回sb.end(),即sb.find(s1_item)==sb.end()表示sb集合内不包含元素s1_item。完整程序如下:
#include <bits/stdc++.h>
using namespace std;
int main(int argc, char const *argv[])
{
int n;
scanf("%d", &n);
vector<set<int> > s(n);
for (int i = 0; i < n; ++i)
{
int num;
scanf("%d", &num);
int temp;
for (int j = 0; j < num; ++j)
{
scanf("%d", &temp);
s[i].insert(temp);
}
}
int k;
scanf("%d", &k);
int a, b;
set<int>:: iterator it;
for (int i = 0; i < k; ++i)
{
scanf("%d%d", &a, &b);
int Nc=0, Nt=s[b-1].size();
for(it=s[a-1].begin(); it!=s[a-1].end(); it++)
{
if(s[b-1].find(*it)==s[b-1].end()) Nt++;
else Nc++;
}
float anw = (float)(Nc*100)/(float)Nt;
printf("%.1f%%\n", anw);
}
return 0;
}