古人云:秀恩爱,分得快。
互联网上每天都有大量人发布大量照片,我们通过分析这些照片,可以分析人与人之间的亲密度。如果一张照片上出现了 K 个人,这些人两两间的亲密度就被定义为 1/K。任意两个人如果同时出现在若干张照片里,他们之间的亲密度就是所有这些同框照片对应的亲密度之和。下面给定一批照片,请你分析一对给定的情侣,看看他们分别有没有亲密度更高的异性朋友?
输入格式:
输入在第一行给出 2 个正整数:N(不超过1000,为总人数——简单起见,我们把所有人从 0 到 N-1 编号。为了区分性别,我们用编号前的负号表示女性)和 M(不超过1000,为照片总数)。随后 M 行,每行给出一张照片的信息,格式如下:
K P[1] ... P[K]
其中 K(≤ 500)是该照片中出现的人数,P[1] ~ P[K] 就是这些人的编号。最后一行给出一对异性情侣的编号 A 和 B。同行数字以空格分隔。题目保证每个人只有一个性别,并且不会在同一张照片里出现多次。
输出格式:
首先输出 A PA
,其中 PA
是与 A
最亲密的异性。如果 PA
不唯一,则按他们编号的绝对值递增输出;然后类似地输出 B PB
。但如果 A
和 B
正是彼此亲密度最高的一对,则只输出他们的编号,无论是否还有其他人并列。
输入样例 1:
10 4
4 -1 2 -3 4
4 2 -3 -5 -6
3 2 4 -5
3 -6 0 2
-3 2
输出样例 1:
-3 2
2 -5
2 -6
输入样例 2:
4 4
4 -1 2 -3 0
2 0 -3
2 2 -3
2 -1 2
-3 2
输出样例 2:
-3 2
代码解释:使用的结构体数组进行存储,并且男女分开存的,在遍历时节省时间
第1点是要注意里面有-0 和0 的区别 所以只能用字符串输入,而且字符串的最少为5个空间,因为忽略了这一点,测试点4找了3个小时的错
第2点要注意会有双方亲密值都为0的测试点,这时相当于双方亲密值都是最高的,直接输出一行,但没有只有1方亲密值为0的测试点,代码中也没有考虑这一点
第3点 abs(0.009)==0 ,小数不能用abs,除法时要把总人数变为float型
代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
typedef struct node{
int total; //总人数
int boy[500]; //记录照片上的男人
int girl[500]; //记录照片上的女人
int boynum; //代表这张照片里男生人数
int girlnum; //代表女生人数
int flag; //记录这张照片有没有男女主角
}ONE;
void FindPAPB(ONE photo[],int sexa,int sexb,int PA,int PB);
void updateFlag(int sex,ONE photo[],int i);
void FindGroupPhoto(int sex,ONE photo[],int *maxloc,float *Intimacy,float GroupPhoto[]);
void FindMaxLoc(int maxloc,float Intimacy,float GroupPhoto[],int loc[],int *top,int *flag,int P);
int n,m; //n总人数 m照片数量
int main()
{
scanf("%d%d",&n,&m);
ONE photo[m];int temp;
for (int i=0;i<m;i++) //初始化
{
photo[i].total=0;
photo[i].girlnum=0;
photo[i].boynum=0;
photo[i].flag=0;
}
char str[10];
for (int i=0;i<m;i++)
{
scanf("%d\n",&(photo[i].total));
for (int j=0;j<photo[i].total;j++)
{
scanf("%s",str); //!!!!!有-0 和 0 必须用字符串区分
temp=atoi(str);
if (!strcmp(str,"-0") || temp<0)
photo[i].girl[photo[i].girlnum++]=temp;
else
photo[i].boy[photo[i].boynum++]=temp;
}
}
//输入男女主角 并标志为男女
char stra[5],strb[5];scanf("%s %s",stra,strb);//!!!!!!字符串长度最少为5 否则测试点4错误
int PA=atoi(stra),PB=atoi(strb),sexa=0,sexb=0; //-1代表女 1代表男
if (!strcmp(stra,"-0") || PA<0)
sexa--;
else
sexa++;
if (!strcmp(strb,"-0") || PB<0)
sexb--;
else
sexb++;
FindPAPB(photo,sexa,sexb,PA,PB); //找照片里是否有男女主角
//GroupPhotoA GroupPhotoB数组下表代表合照的人的绝对值 里面的数代表亲密值
float GroupPhotoA[1001]={0},GroupPhotoB[1001]={0};
int maxlocA=0,maxlocB=0; //maxlocA为数组达到的最大下标 用于循环 节省时间
float IntimacyA=0,IntimacyB=0; //IntimacyA记录最大亲密值
FindGroupPhoto(sexa,photo,&maxlocA, &IntimacyA, GroupPhotoA );
FindGroupPhoto(sexb,photo,&maxlocB, &IntimacyB, GroupPhotoB );
//flag是0代表双方亲密值都没有最大 1代表某一个人亲密值最大 2代表双方亲密值都最大
int flag=0;
int locA[maxlocA],locB[maxlocB],topA=0,topB=0; //找照片里面达到最大亲密值的并记录在locA、locB数组里面 记录着最大的位置
FindMaxLoc(maxlocA,IntimacyA,GroupPhotoA,locA,&topA,&flag,PB);
FindMaxLoc(maxlocB,IntimacyB,GroupPhotoB,locB,&topB,&flag,PA);
//输出 !!!!!! 测试点里面没有只有其中1方最大亲密值为0的 只有测试点3两方亲密值都为0
if (flag==2 || (!IntimacyA && !IntimacyB)) //如果 A 和 B 正是彼此亲密度最高的一对 或者 !!!!!1张照片也没有(测试点3) 只输出这一对
printf("%s %s\n",stra,strb);
else //如果AB不是彼此亲密值最大的一对 则输出亲密值最大的所有人
{
for (int i=0;i<topA;i++)
{
if (sexa<0 )
printf("%s %d\n",stra,locA[i]);//直接由stra输出 不用再分-0的情况
else
printf("%s -%d\n",stra,locA[i]);
}
for (int i=0;i<topB;i++)
{
if (sexb<0 )
printf("%s %d\n",strb,locB[i]);
else
printf("%s -%d\n",strb,locB[i]);
}
}
}
/*!!!!!输入 测试点3类似
10 0
-0 1
输出
-0 1*/
//找照片里有没有男女主角
void FindPAPB(ONE photo[],int sexa,int sexb,int PA,int PB)
{
for (int i=0;i<m;i++) //标志如果只有该女的标志为-1 只有该男的标志为1 都有标志为2
{
for (int j=0;j<photo[i].girlnum;j++)
{
if (sexa<0 && PA==photo[i].girl[j] ) //a是女的并且照片里有
updateFlag(sexa,photo,i);
else if(sexb<0 && PB==photo[i].girl[j]) //b是女的并且照片里有
updateFlag(sexb,photo,i);
}
for (int j=0;j<photo[i].boynum;j++)
{
if(sexa>0 && PA==photo[i].boy[j])
updateFlag(sexa,photo,i);
else if(sexb>0 && PB==photo[i].boy[j])
updateFlag(sexb,photo,i);
}
}
}
//更新结构体里的flag 如果为1代表有男主角 -1代表女主角 2代表都有
void updateFlag(int sex,ONE photo[],int i)
{
if(photo[i].flag) //如果已经有其中一个了
{
photo[i].flag=2;
return;
}
if (sex<0)
photo[i].flag=-1;
else
photo[i].flag=1;
}
//找合照的人
void FindGroupPhoto(int sex,ONE photo[],int *maxloc,float *Intimacy,float GroupPhoto[])
{
for (int i=0;i<m;i++)
{
if (sex>0) //如果是男的 找女的
{
if (!(photo[i].flag==1 || photo[i].flag==2))//如果这张照片没有这男的
continue;
for (int j=0;j<photo[i].girlnum;j++)
{
GroupPhoto[abs(photo[i].girl[j])]+=(1/(float)photo[i].total);//必须有float
if (abs(photo[i].girl[j]) > *maxloc) //maxloc记录GroupPhoto的最大下标 访问时节省时间
*maxloc = abs(photo[i].girl[j]);
if (GroupPhoto[abs(photo[i].girl[j])] > *Intimacy) //Intimacy记录最大亲密值
*Intimacy = GroupPhoto[abs(photo[i].girl[j])]; //不能加abs abs(0.009)=0 //printf("\n%f",abs(0.09));
}
}
else //如果是女的
{
if(!(photo[i].flag==-1 || photo[i].flag==2))// 只有1或0时才中断 或者if (photo[i].flag!=-1 && photo[i].flag!=2)也对
continue;
for (int j=0;j<photo[i].boynum;j++)
{
GroupPhoto[photo[i].boy[j]]+=(1/(float)photo[i].total);
if (abs(photo[i].boy[j]) > *maxloc)
*maxloc = abs(photo[i].boy[j]);
if (GroupPhoto[photo[i].boy[j]] > *Intimacy)
*Intimacy = GroupPhoto[photo[i].boy[j]];
}
}
}
}//找照片里面达到最大亲密值的并记录在locA、locB数组里面 记录着最大的位置
void FindMaxLoc(int maxloc,float Intimacy,float GroupPhoto[],int loc[],int *top,int *flag,int P)
{
for (int i=0;i<=maxloc && Intimacy;i++) //亲密值不能为0 因为GroupPhoto数组的初值全为0
{
if (GroupPhoto[i]==Intimacy)
{
loc[(*top)++]=i; //必须加()
if (i==P || i==-P)
(*flag)++;
}
}
}