PAT_A1063
PAT甲级1063.
目录
A1063
题目
样例
输入:
3
3 99 87 101
4 87 101 5 87
7 99 101 18 5 135 18 99
2
1 2
1 3
输出:
50.0%
33.3%
思路和坑点
使用map容器筛选掉重复的数据,并且使用map映射标记,记录每一个数的归属,属于第一组数据,还是第二组数据,还是共有的。
第一种解法,最后一个擦边过的时间,可能会超时。参见第二种AC代码
AC代码
#include<bits/stdc++.h>
using namespace std;
void check(vector<int> &a,vector<int> &b){ //求解一组数据
unordered_map<int,int> mp; //mp容器记录所有出现过的数字
int cnt=0; //cnt为共有数字的个数
for(int i=0;i<a.size();i++) // 如果该数为第一组所有则标记为1
mp[a[i]]=1;
for(int i=0;i<b.size();i++){
switch(mp[b[i]]){
case 0: mp[b[i]]=2;break; //如果第一组数中没出现过,说明为第二组数所有,标记为2
case 1: mp[b[i]]=3;cnt++;break; //如果第一组也有,第二组也有,共有标记为3,并计数
case 2:
case 3: continue;break; //如果已经标记为特有或者共有,则跳过
}
}
printf("%.1f%%\n",cnt*100.0/mp.size()); //计算结果
}
int main(void){
#ifdef ONLINE_JUDGE
#else
freopen("1.txt","r",stdin);
#endif
int n,k;
scanf("%d",&n);
vector<int> v[n+1];
for(int i=1;i<=n;i++){
int m;
scanf("%d",&m);
v[i].resize(m);
for(int j=0;j<m;j++){
scanf("%d",&v[i][j]);
}
}
scanf("%d",&k);
for(int i=0;i<k;i++){
int a,b;
scanf("%d%d",&a,&b);
check(v[a],v[b]);
}
return 0;
}
AC代码(更优)
感谢张勇同学提供的更优方法
#include<bits/stdc++.h>
using namespace std;
#define MAXN 51 //最多有MAXN组
unordered_map<int,int>G[MAXN]; //创建一个map容器的数组
int main(void){
#ifdef ONLINE_JUDGE
#else
freopen("1.txt", "r", stdin);
#endif
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++){ //读入n组数据,记录在map中
int m;
scanf("%d", &m);
for (int j = 0; j < m; j++){
int num;
scanf("%d", &num);
G[i][num] = 1;
}
}
int k;
scanf("%d", &k);
for (int i = 0; i < k; i++){ //k组查询
int a, b; //查询的组号
int nc = 0,nt = 0; //nc为共同数字个数,nt为不同数字个数
scanf("%d%d", &a, &b);
nt = G[b].size(); //nt初始化为其中一个序列包含的数字个数,然后遍历第二个序列,继续统计
for (auto it = G[a].begin(); it != G[a].end(); it++){
if (G[b].find(it->first) != G[b].end())
nc++; //如果是共有的,nc加一
else
nt++; //如果不是共有的,nt加一
}
float ans = (1.0 * nc) / (1.0 * nt) * 100;
printf("%.1f", ans); puts("%");
}
return 0;
}