“战疫杯”大学生程序设计在线邀请赛(5)

目录

感染源在哪里

输入格式:

输出格式:

输入样例:

输出样例:

思路:

AC代码如下:

病毒序列

输入格式:

输出格式:

输入样例:

输出样例:

样例解释

思路:

AC代码如下:

奇奇怪怪的形状

输入格式:

输出格式:

输入样例:

输出样例:

思路:

AC代码如下:


感染源在哪里

感染源在哪里

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

对于一个病例,如果其曾到过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

代码长度限制

16 KB

时间限制

1000 ms

内存限制

64 MB

思路:

模拟:去重 + 排序

可以使用vector去重的方法

去除重复元素
      vector<string> vec  
      vec.erase(unique(vec.begin(),vec.end()),vec.end());

赛时忘了去除咋写了,就用map解决了

AC代码如下:

#include <bits/stdc++.h>
#define buff                     \
    ios::sync_with_stdio(false); \
    cin.tie(0);                  \
    cout.tie(0)
using namespace std;
const int N = 1009;
int n;
map<string, int> m;
vector<string> s[N];
int cnt = 0;
struct mm
{
    map<string, int> check;
} cf[N];
struct nn
{
    string name;
    double q = 0;
} tt[N];
map<string, int> t;
int cnt2 = 0;
bool cmp(nn x, nn y)
{
    if (x.q != y.q)
        return x.q > y.q;
    else
        return x.name < y.name;
}
int main()
{
    buff;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        string a, b;
        cin >> a >> b;
        if (!m[a])
        {
            m[a] = ++cnt;
        }
        if (!cf[m[a]].check[b])
        {
            cf[m[a]].check[b] = 1;
            s[m[a]].push_back(b);
        }
    }

    for (int i = 1; i <= cnt; i++)
    {
        int num = s[i].size();
        for (int j = 0; j < num; j++)
        {
            string tmp = s[i][j];
            if (!t[tmp])
            {
                t[tmp] = ++cnt2;
                tt[cnt2].name = tmp;
            }
            tt[t[tmp]].q += 1.0 / num;
        }
    }
    sort(tt + 1, tt + 1 + cnt2, cmp);
    for (int i = 1; i <= cnt2; i++)
        cout << tt[i].name << "\n";
}

病毒序列

病毒序列

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

而小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的方式进行结合

代码长度限制

16 KB

时间限制

1000 ms

内存限制

128 MB

思路:

枚举:分别枚举两串的相对位置关系

推荐方法:

约定:两串分别为 a串, b串。

【1】a串固定,b串移动

【2】b串固定,a串移动

枚举所有位置情况所对应的氢键个数,取最大值并输出。

AC代码如下:

#include <bits/stdc++.h>
#define buff                     \
    ios::sync_with_stdio(false); \
    cin.tie(0);                  \
    cout.tie(0)
using namespace std;
const int N = 5009;
char s1[N];
char s2[N];
int n1, n2;
int ans = 0;
int func(char x, char y)
{
    if ((x == 'A' && y == 'U') || (x == 'U' && y == 'A'))
        return 3;
    else if ((x == 'C' && y == 'G') || (x == 'G' && y == 'C'))
        return 2;
    else
        return 0;
}
void check1(int idx)
{
    int sum = 0;
    for (int i = idx, j = 0; i < n2 && j < n1; i++, j++)
    {
        sum += func(s2[i], s1[j]);
    }
    if (sum > ans)
        ans = sum;
}

void check2(int idx)
{
    int sum = 0;
    for (int i = idx, j = 0; i < n1 && j < n2; i++, j++)
    {
        sum += func(s1[i], s2[j]);
    }
    if (sum > ans)
        ans = sum;
}
int main()
{
    buff;
    cin >> s1;
    cin >> s2;
    n1 = strlen(s1);
    n2 = strlen(s2);
    // s1移动
    for (int i = 0; i < n2; i++)
    {
        check1(i);
    }
    // s2移动
    for (int i = 0; i < n1;i++)
    {
        check2(i);
    }
    cout << ans << "\n";
}

奇奇怪怪的形状

奇奇怪怪的形状

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

输入格式:

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

输出格式:

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

输入样例:

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

2 1
1 1

输出样例:

20

代码长度限制

16 KB

时间限制

1000 ms

内存限制

128 MB

思路:

关于 由立方体组成的几何体的表面积 :

我们可以分为6个视角来分别算 每个视角对应的面积,最后加一起就是表面积。

也可以是两(四)个视图(俯视or仰视,左or右视图)的面积 和* 2

S(表面积) =[ S(俯or仰) + S(左or右)] * 2

AC代码如下:

#include <bits/stdc++.h>
#define buff                     \
    ios::sync_with_stdio(false); \
    cin.tie(0);                  \
    cout.tie(0)
using namespace std;
int a, b, x, y;
int s[4];
int main()
{
    buff;
    cin >> a >> b >> x >> y;
    int ans = 0;
    //四个视角

    //正 + 后
    int one = max(a, x);
    int two = max(b, y);
    ans += (one + two) * 2;

    //左 + 右
    one = max(a, b);
    two = max(x, y);
    ans += (one + two) * 2;

    //上+下
    ans += 4 * 2;

    cout << ans << endl;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Joanh_Lan

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

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

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

打赏作者

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

抵扣说明:

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

余额充值