L2-005 集合相似度 (25分)
给定两个整数集合,它们的相似度定义为:Nc /Nt ×100%。其中Nc
是两个集合都有的不相等整数的个数,Nt是两个集合一共有的不相等整数的个数。你的任务就是计算任意一对给定集合的相似度。
输入格式:
输入第一行给出一个正整数N(≤50),是集合的个数。随后N行,每行对应一个集合。每个集合首先给出一个正整数M(≤10^4),是集合中元素的个数;然后跟M个[0,10 ^9 ]区间内的整数。
之后一行给出一个正整数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%
#include<stdio.h>
#include<stdlib.h>
int num[2001];
int deno[2001];
int cmp(const void* a, const void* b)
{
return *(int*)a > *(int*) b ? 1 : -1;
}
int main()
{
int N, M, K, g1, g2, c, offset;
bool equal = false;
int index = 0;
scanf("%d", &N);
int** gather = (int**)malloc(sizeof(int*) * N);
for (int i = 0; i < N; i++)
{
int j = 0;
offset = 0;
scanf("%d", &M);
gather[i] = (int*)malloc(sizeof(int) * M);
for (j = 0; j < M; j++)
{
equal = false;
scanf("%d", &c);
for (int k = 0; k < j; k++) //判断集合中是否存在相同数
if (c == gather[i][k]){equal = true;break;}
if (!equal)gather[i][j - offset] = c;
else offset += 1;
}
qsort(gather[i], j-offset, sizeof(int), cmp);
gather[i][j - offset] = -1; //集合含有的都是正数,可以用-1来标记结尾
}
scanf("%d", &K);
for (int i = 0; i < K; i++)
{
num[i] =0; //都有的数
deno[i] = 0; //一共有的数
scanf("%d %d", &g1, &g2);
g1 -= 1; g2 -= 1;
int cindex = 0;
while (gather[g1][index] != -1 && gather[g2][index] != -1)
{
//找与gather[g1][index]相等的数,找到后num+1
if (gather[g1][index] == gather[g2][index])num[i] += 1;
else
{
if (cindex != -1)
while (true)
{
if (gather[g2][cindex] == -1) { cindex = -1;break; }
//集合2遍历完毕都没有找到正确的值,因为已经对集合排序,
//所以gather[g1][index]之后的所有数都不会在g2中找到相同的
if (gather[g2][cindex] > gather[g1][index])break;
//由于所有数递增排序,g2[cindex]大于g1[index]时说明g2中没有与g1[index]相同的数,结束遍历
if (gather[g2][cindex] == gather[g1][index]){num[i] += 1;break;}
//找到g2中一个与g1[index]相同的数后,num+1
cindex++;
}
}
deno[i] += 2; //每次循环deno+2,循环结束后将deno减去num可以得到正确的deno
index++;
}
//集合大小不一,若集合1先遍历完,集合2每多1个数,deno+1
//集合2先遍历完继续像之前那样找与gather[g1][index]相等的数,直到循环到-1
if (gather[g1][index] == -1)while (gather[g2][index++] != -1)deno[i] += 1;
else if(gather[g2][index]==-1)while (gather[g1][index] != -1)
{
if (cindex != -1)
while (true)
{
if (gather[g2][cindex] == -1) { cindex = -1; break; }
if (gather[g2][cindex] > gather[g1][index])break;
if (gather[g2][cindex] == gather[g1][index]){num[i] += 1;break;}
cindex++;
}
index++;
deno[i] += 1;
}
deno[i] -= num[i];
index = 0;
}
for (int i = 0; i < K; i++)
{
printf("%.2f%%", num[i] * 100.0f / deno[i]);
if (i != K - 1)putchar('\n');
}
}