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

目录

1 我的账本

2 核酸检测扫码

3 辛苦的楼长

4 等待做核酸


1 我的账本

当前疫情防控形势严峻,学校为了减少同学们因为吃饭造成的聚集,规定一个寝室每次派个代表出去买饭,小W寝室的6人(编号1-6)决定每次抽签派一个人去买6份同样的套餐。但是每次买完饭后立刻转账又比较麻烦,于是他们约定每次去买饭的人先垫付,等疫情结束后再统一结算。

现在给你宿舍封闭管理期间的n顿饭中每次买饭人的序号和每份饭的单价,问疫情结束后每个人关于饭钱的收支状况?

输入格式:

第一行一个正整数n,表示有n顿饭
下面n行,第i行两个正整数x,y表示第i顿饭由x去买饭,每份饭单价y元。

输出格式:

一行六个整数表示每个人欠别人的钱或者别人欠他的钱。
如果他欠了别人钱,输出负数。
如果别人欠他的钱,输出正数 。

输入样例:

3
1 5
2 10
3 5

输出样例:

10 40 10 -20 -20 -20

注意行末不能有多余空格

样例解释1

1号欠2号5元,不欠3号,4号、5号、6号各欠1号5元,故1号输出10
1号、3号欠2号5元,4号、5号、6号各欠2号10元,故2号输出40
3号与1号同理
4号欠1号5元,欠2号10元,欠3号5元,故4号为-20
5号、6号与4号同理

数据范围与提示

1≤n≤21
1≤x≤6
4≤y≤15

思路:开一个长度为6的数组,带一次饭,带饭者 + 5 * 带饭钱数,其他人 - 带饭钱数

代码如下

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <vector>
#include <map>
#include <string>
#include <cstring>

using namespace std;

typedef long long LL;

const int N = 1e5+10;

int T;

int main()
{
    scanf("%d", &T);
    int a[10] = {0};

    while(T -- )
    {
        int x, y;
        scanf("%d%d", &x, &y);
        a[x] += 5*y;
        for(int i = 1; i <= 6; i ++ )
            if(i != x) a[i] -= y;
    }

    for(int i = 1; i < 6; i ++ )
        printf("%d ", a[i]);
    printf("%d\n", a[6]);

    return 0;
}

2 核酸检测扫码

受疫情影响,小明同学现在每天需要下楼进行核酸检测。检测时,需要先用郑好办 APP 扫描二维码并填写个人信息以便统计核酸检测结果。

a09c6d5038bc7a959b8d66f3d1081b6f.png

小明对于二维码的构造很是好奇。据了解,二维码中的黑白可以用来表示二进制中的 0/1 。且二维码的左上角,右上角,左下角有三个形态固定的特殊方阵,用做扫码时的位置标定。通过确定这三个特殊方阵的位置,进而确定整个二维码图形在照片中的位置。除了这三个特殊方阵外,其他位置的 0/1 取值由特定方法产生,表示扫描二维码后的交互动作内容。

小明现在重点关注二维码图像中的特殊方阵,想定位仅有的三个特殊方阵。为了简化问题,你可以将二维码视为n∗m的 01 方阵,将用于标定的特殊方阵视为 8×8 的方阵,其形态如下:

11111111
10000001
10111101
10111101
10111101
10111101
10000001
11111111

现在为了安全起见,二维码标定用的三个特殊矩阵不再位于原方阵的三个角上,而是随机的分布在原方阵内(仍然保证特殊方阵之间不会相互重叠),请你找出这三个特殊方阵的位置(每个特殊方阵左上角的坐标)。

输入格式:

第一行n m,表示二维码对应01矩阵的大小(0<n,m≤1000)
第二行起,给出n行m列的01矩阵

输出格式:

输出共 3 行,每行两个整数,分别代表一个特殊方阵左上角所位于的行编号和列编号(行编号从上向下数分别是 0, 1, 2, 3, ...;列编号从左向右数分别是 0, 1, 2, 3, ...)。三组坐标将行编号作为第一关键字,列编号作为第二关键字升序排序后输出。

输入样例:

20 20
11111111100111111111
10000001011010000001
10111101111110111101
10111101111110111101
10111101111110111101
10111101000010111101
10000001101110000001
11111111001111111111
11111000110000010111
11110000011100010010
00111011000101011101
00110011010001110001
11111111100010100000
10000001110101001101
10111101010100000101
10111101010111100000
10111101000011111001
10111101001111001001
10000001111100000011
11111111110110001001

输出样例:

0 0
0 12
12 0

思路: 题意为找到特定矩形图案出现的3个位置,可用一个string数组将要查找的图案保存下来,

遍历二维数组,每次在起点处,剪切下长度为8的字符串数组,然后向下比较8行,若8行都成立则

该起点成立,加入数组中(因为已经确定数组长度为3,开3个长度就好)

代码如下

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <vector>
#include <map>
#include <string>
#include <cstring>

#define fast ios::sync_with_stdio(false),cin.tie(0)

using namespace std;

typedef pair<int, int> PII;
typedef long long LL;

const int N = 1010;

int T;
int f1, s1, f2, s2;

vector<PII> v;
string x[8] = {"11111111", "10000001", "10111101", "10111101", "10111101", "10111101", "10000001", "11111111"};

int main()
{
    int n, m;
    scanf("%d %d", &n, &m);
    string s[N];
    for(int i = 0; i < n; i ++ )
    {
        cin >> s[i];
    }

    for(int i = 0; i <= n - 8; i ++ )
    {
        for(int j = 0; j <= m - 8; j ++ )
        {
            int k, cnt = 0;
            for(k = 0; k < 8; k ++ )
            {
                //cout << k << " " << x[k] << " " << s[i+k].substr(j, 8) << endl;
                if( x[k] == s[i+k].substr(j, 8) ) cnt ++;
            }
            if(cnt == 8) v.push_back({i, j});
        }
    }

    sort(v.begin(), v.end());

    for(int i = 0; i < 3; i ++ )
        printf("%d %d\n", v[i].first, v[i].second);

    return 0;
}

3 辛苦的楼长

疫情防控期间,要尽最大努力的保障同学们饮食!楼长们正在统计订饭的人数,一共是三个园区的统计表放在了一个文档里,有一些粗心的同学没有分清园区,错误的将自己的信息填到了其他园区的统计表上。身为帮助楼长的热心同学,你需要写一个程序将所有同学分到正确的园区并统计各个园区需要准备的早饭、午饭、晚饭的份数。

输入格式:

三组数据,每一组代表错误的园区的统计表。

每一组数据第一行是这个统计表上的信息数目n。
该组数据第2行到第n+1行是具体的信息,分别是:宿舍楼(格式为“园区(拼音,松:song,菊:jv,柳:liu)+楼号(数字)”中间无空格,例如“jv4”就表示菊园四号楼),宿舍号,早饭订饭数量,午饭订饭数量,晚饭订饭数量(某个寝室的信息只提交一次,不会重复)。

输出格式:

三组数据,分别代表三个园区的数据状况,按照“松-菊-柳”的顺序输出。

每组数据第一行有四个数,分别是该园区实际订餐的寝室数目,该园区总共订的早餐数目,午餐数目,晚餐数目。

然后输出该园区的所有正确的订单信息,排序输出(保证楼号非递减输出,若是楼号相同的订单则按找寝室号递增输出)。

输入样例:

在这里给出一组输入。例如:

4
song6 321 1 2 1
jv4 422 6 6 6
liu2 211 4 5 3
jv1 331 1 5 4
1
song2 333 6 6 6
1
jv6 612 2 3 3

输出样例:

2 7 8 7
song2 333 6 6 6
song6 321 1 2 1
3 9 14 13
jv1 331 1 5 4
jv4 422 6 6 6
jv6 612 2 3 3
1 4 5 3
liu2 211 4 5 3

数据范围

楼号保证在范围[0-9],房号范围为(100~999),订餐数目总数小于1000,每个园区订餐信息不超过20条。

思路

开长度为3的二维结构体,第一维存园区(song ,liu,ju),第二维存,该园区的宿舍楼(song3,song2,liu6,ju4等);

额外开 st[3] 数组,存该园区的宿舍数量,每次插入后 st++,移到下一个要存的位置

开 ts[3][3] 数组,存每个园区的 3 种饭中每种饭的数量之和;

对结构体排序(cmp),保证输出正确 

代码如下

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <vector>
#include <map>
#include <string>
#include <cstring>

#define fast ios::sync_with_stdio(false),cin.tie(0)

using namespace std;

typedef pair<int, int> PII;
typedef long long LL;

const int N = 1010;

struct Node
{
    string name;
    int num;
    int a, b, c;
}peo[3][N];

int st[3], ts[3][3];

bool cmp(Node a, Node b)
{
    if(a.name != b.name) return a.name < b.name;
    else return a.num < b.num;
}

int main()
{
    int T = 3;
    while(T -- )
    {
        int n;
        scanf("%d", &n);
        while(n -- )
        {
            int t;
            string s;
            cin >> s;
            int num, a, b, c;
            cin >> num >> a >> b >> c;
            if(s[0] == 's') t = 0;
            else if(s[0] == 'j') t = 1;
            else t = 2;
            ts[t][1] += a, ts[t][2] += b, ts[t][3] += c;
            peo[t][st[t]++] = {s, num, a, b, c};
        }
    }

    for(int i = 0; i < 3; i ++ )
        sort(peo[i], peo[i] + st[i], cmp);

    for(int i = 0; i < 3; i ++ )
    {
        printf("%d %d %d %d\n", st[i], ts[i][1], ts[i][2], ts[i][3]);
        for(int j = 0; j < st[i]; j ++ )
        {
            cout << peo[i][j].name ;
            printf(" %d %d %d %d\n", peo[i][j].num, peo[i][j].a, peo[i][j].b, peo[i][j].c);
        }
    }



    return 0;
}

4 等待做核酸

最近新一轮新冠疫情来势汹汹,形势极为严峻,为了保障全体师生的安全,在校师生需要每天做核酸。每天医护人员到达的时间都是不固定的,为了简化问题,假设医护人员到达的时间是整分钟(如10:05:00),并且知道医护人员到达时间的区间,医护人员在这个区间的任意时刻到达的概率相同,核酸检测结束的时间为23:59。在校学生妙酱每天都会按时做核酸,并且妙酱出来做核酸的时间也为整分钟,妙酱想知道自己等多久可以做核酸。由于开始做核酸的时间是不固定的,请你求出妙酱做核酸等待时间(分钟)的期望,忽略妙酱排队等待的时间。

输入格式:

第一行医护人员到达时间的区间(hh:mm-hh:mm)。

第二行cc出来做核酸的时间(hh:mm)。

输入的时间均在一天内。

输出格式:

等待时间(分钟)的期望值,保留两位小数。

输入样例:

10:00-10:29
10:15

输出样例:

3.50

思路:数学期望 == 求均值,若医护人员早于妙酱,则妙酱等的时间为0;若迟于妙酱,则res 加上妙酱等待的时间,最后res/区间长度的得出结果,

注:区间长度为 (r - l + 1)

代码如下

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <vector>
#include <map>
#include <string>
#include <cstring>

#define fast ios::sync_with_stdio(false),cin.tie(0)

using namespace std;

typedef long long LL;

const int N = 1e5+10;

int main()
{
    int x, y;
    int f1, s1, f2, s2;
    scanf("%d:%d-%d:%d", &f1, &s1, &f2, &s2);
    scanf("%d:%d", &x, &y);

    LL res = 0;
    int sum1 = f1 * 60 + s1, sum2 = f2 * 60 + s2, sum = x * 60 + y;
    for(int i = sum1; i <= sum2; i ++ )
    {
        if(i > sum) res += i - sum;
    }

    printf("%.2f\n", res*1.0/(sum2 - sum1 + 1));

    return 0;
}

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

AC自动寄

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

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

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

打赏作者

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

抵扣说明:

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

余额充值