郑州大学“战疫杯”大学生程序设计在线邀请赛(5)(C++题解+详细思路)2022年5月13日

本文涵盖了三个技术问题:1) 如何通过病例的行动轨迹分析疫情源头;2) 如何计算两个病毒基因序列结合后的最大氢键数;3) 如何确定由立方体组成的几何体的表面积。这些问题分别涉及数据分析、生物信息学和几何学,通过编程解决,为理解和应对疫情提供科学依据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1 感染源在哪里

2 病毒序列

3 奇奇怪怪的形状


1 感染源在哪里

通过最近的一次核酸检测,疫情防控小组检测到了若干个阳性人员,通过调取行程码数据,防控小组获取到了这些病例曾经去过的地点。现在希望对这些地点做源头可能性分析,来找出哪些地点更有可能是本次疫情的源头。

对于一个病例,如果其曾到过a,b,c三个地点,那么这三个地点都会在其源头可能得分上增加1/3,如果某个病例曾经去过a,c两个地点,那么这两个地点作为源头的得分都会增加1/2,如果只去过一个地点的病例,那么该地点作为源头的概率很高,我们给这个地点的得分增加1。

简而言之,如果一个病例去过n个地点,那么这n个地点都会得到1/n的得分。现在给你所有病例去过的地点的情况,你能否分析出每个地点作为源头的可能性大小顺序?

输入格式:

第一行一个整数n(1≤n≤1000),表示记录的条数
其后n行,每行两个不为空的字符串a,b(1≤∣a∣,∣b∣≤10),仅包含小写字母。其中a代表病例的名字,b代表地点。

注意:当出现有人多次去同一地点时,只计算一次

输出格式:

输出若干行,每行代表一个地点名,代表所有地点作为源头的得分从高到低排序的结果。如果有多个地点得分相同,地点名字典序小的优先。

输入样例:

6
xiaoa adian
xiaob adian
xiaob bdian
xiaoc adian
xiaoc bdian
xiaoc cdian

输出样例:

adian
bdian
cdian

思路:

        map套map,第一层map的 key 为姓名, value 为 map;第二层的 key 为地点,value为 去过的地点,转化为 vector,排序输出即可

注意:

       浮点数判断相等: fabs(a.second - b.second) >= 1e-8

        

代码如下:

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<string, double> PSD;

const int N = 1010;

int n, m;
int v[N], w[N];
map<string, map<string, int> > mp;
map<string, double> sp;
vector<PSD> p;

bool cmp(PSD a, PSD b)
{
    if( fabs(a.second - b.second) >= 1e-8) return a.second > b.second;
    else if(a.first != b.first) return a.first < b.first;
}

int main()
{
    scanf("%d", &n);

    while(n -- )
    {
        string name, s;
        cin >> name >> s;
        mp[name][s] = 1;
    }

    double f;
    for(auto it : mp)
    {
        int sum = it.second.size();
        for(auto t : it.second)
        {
            sp[t.first] += 1.0/sum;
        }
    }

    for(auto i : sp)
        p.push_back({i.first, i.second});

    sort(p.begin(), p.end(), cmp);

    for(int i = 0; i < p.size(); i ++ )
        cout << p[i].first << endl;

    return 0;
}

2 病毒序列

时至至今,疫情还没结束,战斗并未停止!现如今,疫情肆虐全球,疫情的传播加速了病毒的变异,α病毒,β病毒,δ病毒,相继出现...

而小A对病毒的变异来了兴趣,带着高中学过的生物知识,小A了解到病毒可以表示为由A,U,C,G四种碱基组成的基因序列,而病毒的变异便来自于不同基因序列结合。在此,我们将两个不同的基因序列的结合定义为:两个基因序列上下排布,通过一定的错位,使得两个基因序列的部分碱基可以对应起来,若分属两个基因序列的A与U对应则形成3个氢键,若分属两个序列的C与G对应会形成2个氢键,如图所示:

顽固的病毒为了保证自己结构的稳定性,在变异过程中总会选择形成氢键个数最大的方式进行结合。现在给定两个基因序列,他们结合后的氢键个数是多少?

PS:题目描述的“结合”仅仅为本题目描述所定义,不一定符合真实的生物学性质。

输入格式:

两行,每行一个字符串,分别是两个待结合的基因序列。(保证字符串只有A,U,C,G组成,且字符串的长度小于等于5000).

输出格式:

一行一个整数,表示结合后的最大氢键个数。

输入样例:

AGC
UUCG

输出样例:

7

样例解释

共有6种可能的结合方式

AGC
UUCG

AGC
 UUCG
    
AGC
  UUCG
         
 AGC
UUCG

  AGC
UUCG

   AGC
UUCG

其中形成氢键的个数分别为:3,0,0,7,0,0
则病毒序列会选择氢键个数为7的方式进行结合

思路:

        本人有点菜,不会高级的算法,,这里就给个暴力的思路吧!(求大佬指导!!!)

         暴力我觉得也不太好搞,,由前面超出,后面超出两种情况。对于这种我们可以用空格补全前面和后面超出的部分,补充的空格的长度为第一个数组的长度,前补充一个a字符串,后补充一个a字符串,然后让a再b上遍历即可。

样例:

        补充空格后为:

        AGC   

        空空空UUCG空空空


代码如下:

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<string, double> PSD;

const int N = 1010;

int n1, n2, m1, m2;
string a, b;

int main()
{
    cin >> a >> b;

    string t;
    for(int i = 0; i < a.size(); i ++ )
        t += " ";
    string ta, tb;
    ta += a;
    tb += t + b + t;

    //cout << ta << endl;
    //cout << tb << endl;

    for(int i = 0; i < ta.size(); i ++ )
        if(ta[i] == 'A') ta[i] = 'U';
        else if(ta[i] == 'U') ta[i] = 'A';
        else if(ta[i] == 'C') ta[i] = 'G';
        else ta[i] = 'C';

    int res = 0;

    for(int i = 0; i < tb.size() - ta.size(); i ++ )
    {
        int t = 0;
        for(int j = 0, k = i; j < ta.size() && k < tb.size(); j ++, k ++ )
        {
            if(ta[j] == tb[k])
            {
                if(ta[j] == 'A' || ta[j] == 'U') t += 3;
                else t += 2;
            }
        }
        res = max(res, t);
    }

    cout << res << endl;

    return 0;
}

3 奇奇怪怪的形状

小凡有一张边长为2的正方形白纸,上面画了2×2个边长为1的格子,每个格子上可以放置棱长为1的立方体。小凡手中有若干个棱长为1的立方体,他随机地在每个格子上放置一些立方体,求由这些立方体组成的几何体的表面积。

输入格式:

输入两行,每行两个不超过100的正整数,代表从俯视的角度看,白纸所画每个格子上立方体的数量。

输出格式:

输出一行,包含一个整数,表示几何体的表面积。

输入样例:

上图对应的输入数据如下:

2 1
1 1

输出样例:

20

 思路:

        求面积,上和下面积固定 和为 8,左右面积等,前后面积等,只求一个(左面+前面) * 2即可。

左面面积等于 输入的数据中的两行中每行的最大值的和,前面面积等于输入的数据中的两列中每列最大值的和

代码如下:

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<string, double> PSD;

const int N = 1010;

int n1, n2, m1, m2;

int main()
{
    int res = 0;
    scanf("%d %d", &n1, &n2);
    scanf("%d %d", &m1, &m2);

    res = 8;
    res += 2 * max(n1, m1) + 2 * max(n2, m2);
    res += 2 * max(n1, n2) + 2 * max(m1, m2);

    printf("%d\n", res);

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AC自动寄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值