天梯赛训练题12

L2-4 秀恩爱分得快 (25 point(s))

古人云:秀恩爱,分得快。

互联网上每天都有大量人发布大量照片,我们通过分析这些照片,可以分析人与人之间的亲密度。如果一张照片上出现了 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
  • 代码: 

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rep(i,a,b) for(int i=(a);i<(b);++i)
#define maxn 4019
int n,m,k[maxn],A,B,sexa,sexb;
int fu[maxn],pic[maxn][maxn],pwa[maxn],pwb[maxn];
double pa[maxn],pb[maxn];
vector<int>ans1,ans2;

struct gg
{
    int id;//人的编号
    double v;//与A或B的亲密程度
} p1[maxn],p2[maxn];

int read(char*str,int ans,int *fu_)
{
    if(str[0]=='-')
    {
        int len=strlen(str);
        rep(t,1,len)
        ans=ans*10+str[t]-'0';
        *fu_=-1;
    }
    else
    {
        int len=strlen(str);
        rep(t,0,len)
        ans=ans*10+str[t]-'0';
        *fu_=0;
    }
    return ans;
}

void getpwith_(int index,int row)
{
    memset(pwa,0,sizeof(pwa));
    int sex=index==1?sexa:sexb;

    rep(j,0,k[row])
    {
        int peo=pic[row][j];
        if(fu[peo]!=sex)
        {
            if(index)
                pwa[peo]=1;
            else
                pwb[peo]=1;
        }
    }
}

int cmp(gg x,gg y)
{
    if(x.v!=y.v)
        return x.v>y.v;
    return x.id<y.id;
}

int main()
{
    //字符串输入:考虑输入-0的情况
    //字符串输出:考虑输入含-0的情况
    scanf("%d%d",&n,&m);
    rep(i,0,m)
    {
        scanf("%d",&k[i]);
        char str[maxn];//局部使用

        //(1)读取pic[][]:存储出现过的每张图片里的具体人物编号和性别
        rep(j,0,k[i])
        {
            scanf("%s",str);
            //读取多位数
            int fu_;
            pic[i][j]=read(str,pic[i][j],&fu_);
            fu[pic[i][j]]=fu_;
        }
    }
    char AA[maxn],BB[maxn];
    scanf("%s%s",AA,BB);
    A=read(AA,0,&sexa);
    B=read(BB,0,&sexb);


    /******特判,当某个人和谁的好感度都是0,这时候只输出所有异性**************************/
    rep(i,0,n){
        if(fu[i]==sexa)
            pa[i]+=-1;
        if(fu[i]==sexb)
            pb[i]+=-1;
    }

    /***********************************************/
    //(2)计算flaga,flagb(局部变量):标记计算m张图片里是否出现过A,B
    rep(i,0,m)
    {
        int flaga=0;
        int flagb=0;
        rep(j,0,k[i])
        {
            if(pic[i][j]==A)
                flaga=1;
            if(pic[i][j]==B)
                flagb=1;
        }

        if(flaga) //计算A在局部和每个人同框的次数
        {
            getpwith_(1,i);
            rep(j,0,k[i])
            pa[pic[i][j]]+=pwa[pic[i][j]]/double(k[i]);
        }
        if(flagb)//计算B在局部和每个人同框的次数
        {
            getpwith_(0,i);
            rep(j,0,k[i])
            pb[pic[i][j]]+=pwb[pic[i][j]]/double(k[i]);
        }
    }

    rep(i,0,n)
        p1[i].id=i,p1[i].v=pa[i],p2[i].id=i,p2[i].v=pb[i];

    sort(p1,p1+n,cmp);
    sort(p2,p2+n,cmp);

    double maxa=p1[0].v;
    rep(i,0,n)
    {
        if(p1[i].v!=maxa)
            break;
        else
            ans1.push_back(p1[i].id);
    }

    double maxb=p2[0].v;
    rep(i,0,n)
    {
        if(p2[i].v!=maxb)
            break;
        else
            ans2.push_back(p2[i].id);
    }

    /*********************输出****************************/
    int len1=ans1.size();
    int f1=0;
    rep(i,0,len1)
    {
        if(pa[ans1[i]]==pa[B])
            f1=1;
    }

    int len2=ans2.size();
    int f2=0;
    rep(i,0,len2)
    {
        if(pb[ans2[i]]==pb[A])
            f2=1;
    }

    if(f1&&f2)
    {
        if(sexa==-1)
            cout<<'-'<<A<<" ";
        else
            cout<<A<<" ";
        if(sexb==-1)
            cout<<'-'<<B<<endl;
        else
            cout<<B<<endl;
    }
    else
    {
        rep(i,0,len1)
        {
            if(sexa==-1)
                cout<<'-'<<A<<" ";
            else
                cout<<A<<" ";
            if(fu[ans1[i]]==-1)
                cout<<'-'<<ans1[i]<<endl;
            else
                cout<<ans1[i]<<endl;
        }
        rep(i,0,len2)
        {
            if(sexb==-1)
                cout<<'-'<<B<<" ";
            else
                cout<<B<<" ";
            if(fu[ans2[i]]==-1)
                cout<<'-'<<ans2[i]<<endl;
            else
                cout<<ans2[i]<<endl;
        }

    }

    return 0;
}
  • 思路:

  1. 将每个人的性别存如数组,如0号对应性别是男,则fu[0]=1,否则fu[0]=0;
  2. 用两个数组分别表示每个人与A,B的好感度:pa[某人]=某人与A的好感度;pb[某人]=某人与B的好感度。
  3. 遍历n个人,如果这个人和A是同性(包括A和A自身),pa[某人]=-1;pb同理
  4. 遍历m张照片,判断每张照片中是否出现过A,如果出现过,将这张照片中所有的异性用一个数组元素标记为1,最后将被标记过的异性对应的临时数组元素的值++;出现过B同理。
  5. 遍历所有人,pa[某人]+=临时数组每个元素值处以K[i],i代表照片i。pb同理
  6. 根据pa,pb对所有人进行排序。得到和A关系度最高的人的id,B同理
  7. 输出
  • 需要特判的数据:

    1)
    Input:
    8 3
    5 -7 0 -5 3 2
    3 4 1 6
    0 
    4 -5
    
    Output:
    4 -5
    4 -7
    -5 0
    -5 2
    -5 3
    
    2)
    出现某人编号为-0
    输出的时候也得是-0
    (不详细给出数据)

     

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
天梯赛(ACM)是一种面向计算机竞赛的比赛形式,即ACM国际大学生程序设计竞赛。这项比赛旨在促进学生的计算机科学技能和创新思维,并且是计算机专业学生之间最有声望和重要的竞赛之一。 在天梯赛中,参赛队伍需要在规定的时间内解决多个问,这些问通常是涉及算法、数据结构、自动机等计算机科学领域的难。比赛中,每个队伍通常有三名队员组成,他们需要一起分析问、设计算法,并通过程序编码来解决问。此外,比赛规定了每个目的时间和内存限制,参赛队伍需要在这些限制下得出正确的结果。 在天梯赛中,要想在短时间内解决尽可能多的问,参赛队伍必须具备扎实的计算机科学基础知识,并且具有良好的团队合作和沟通能力。他们需要能够迅速分析问、抽象问、设计高效算法,并且通过编程实现。此外,参赛队伍在备赛阶段也需要大量的刷训练,以提高解能力和熟悉常见的问类型。 天梯赛不仅考察了参赛队伍的计算机科学技术水平,也考察了他们的解决问的能力、团队协作能力和时间管理能力。此外,天梯赛也为参赛队伍提供了展示和交流的机会,他们可以与其他参赛队伍分享经验、学习他们的解思路,从中得到启发和提高。 总之,天梯赛是一项注重计算机科学技术和创新能力的竞赛,通过比赛的形式促进学生的学习、交流和提高。它是计算机竞赛中最具代表性和声望的竞赛之一,也是培养优秀计算机科学人才的重要途径之一。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值