目录
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;
}