L2-005 集合相似度

L2-005 集合相似度 (25分)

给定两个整数集合,它们的相似度定义为:Nc​ /N​t​​ ×100%。其中N​c
​​是两个集合都有的不相等整数的个数,N​t​是两个集合一共有的不相等整数的个数。你的任务就是计算任意一对给定集合的相似度。

输入格式:
输入第一行给出一个正整数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');
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值